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

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

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

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