Когда нам нужно иметь конструктор по умолчанию?

Мой вопрос прост. Когда нам нужно иметь конструктор по умолчанию? См. Следующий код:

class Shape
{
    int k;

public:
    Shape(int n) : k(n) {}
    ~Shape() {}
};

class Rect : public Shape
{
    int l;

public:
    Rect(int n): l(n)
    {}      //error C2512: 'Shape' : no appropriate default constructor available

    ~Rect() {}
};
  • Почему компилятор не генерирует конструктор по умолчанию нулевого аргумента неявно в классе Rect?

  • Как мне известно, если класс (Rect) получен из другого класса (Shape), который имеет конструктор по умолчанию (либо неявно сгенерированный, либо явно предоставленный), конструктор по умолчанию должен быть сгенерирован компилятором.

Ответ 1

Конструктор по умолчанию не синтезируется, если вы создали свой собственный конструктор с аргументами. Поскольку вы дали Shape собственный конструктор, вам придется явно выписать конструктор Shape умолчанию:

class Shape
{
      int k;

  public:
      Shape() : k(0) {}
      Shape(int n) : k(n) {}
      ~Shape() {}
};

(Вы можете ~Rect() {} пустые определения ~Rect() {}, так как они будут синтезированы.)

Тем не менее, мне кажется, что вам не нужен конструктор по умолчанию для Shape. Пусть Rect правильно построит базу Shape:

class Shape
{
      int area; // I've had to guess at what this member means. What is "k"?!

  public:
      Shape(const int area)
         : area(area)
      {}
};

class Rect : public Shape
{
     int l;
     int w;

  public:
     Rect(const int l, const int w)
        : Shape(l*w)
        , l(l)
        , w(w)
     {}
};

Также обратите внимание, что этот пример часто цитируется как злоупотребление ОО. Подумайте, действительно ли вам нужно наследование здесь.

Ответ 2

Конструктор по умолчанию будет генерироваться автоматически компилятором, если не определены другие конструкторы. Независимо от любого наследования.

А также вам нужно создать свой базовый класс, вызвав:

Rect( int n ) : Shape( n ), l(n)
{
}

Ответ 3

Компилятор определит значение по умолчанию ctor тогда и только тогда, когда вы явно не объявляете какие-либо ctors.

Обратите внимание, что важно объявить конструктор, не обязательно определяя его. Это довольно распространено, например, объявлять частный ctor и никогда не определять его, чтобы предотвратить компилятор от неявного определения каких-либо других.

Изменить: Также обратите внимание, что С++ 11 имеет синтаксис =default для работы с такими ситуациями, как ваш.

Ответ 4

См. это для полного поведения конструкторов С++ WRT: http://en.wikipedia.org/wiki/Default_constructor

Простой ответ заключается в том, что если вы укажете конструктор, компилятор не будет создавать по умолчанию для вас.

Это правило применимо и к Java.

Ответ 5

Конструктор по умолчанию генерируется только в том случае, если вы не определили никаких других конструкторов.

Предположительно, если вам нужна специальная инициализация в классе, конструктор по умолчанию не будет делать правильные вещи.

Ответ 6

Как вы определили Constructor for Shape, ожидая целое число, вы заменили конструктор по умолчанию, сделав это. Поэтому, если вы расширяете форму, вы должны передать целочисленное значение суперклассу.

Ответ 7

Компилятор создает конструктор по умолчанию в случае, если вы не определили какой-либо конструктор. Но если вы определили какой-либо конструктор, который принимает некоторый аргумент или нет. Компилятор будет использовать этот конструктор и не будет генерировать конструктор по умолчанию с нулевым аргументом.