Должен ли я вызвать конструктор по умолчанию базового класса в списке инициализации? - PullRequest
15 голосов
/ 25 апреля 2011
class A : public B
{
  ...
}

// case I : explicitly call the base class default constructor
A::A() : B()
{
  ...
}

// case II : don't call the base class default constructor
A::A() // : B()
{
  ...
}

Случай II равен случаю I?

Для меня я предполагаю, что конструктор по умолчанию базового класса B НЕ вызывается в случае II. Однако, несмотря на то, что все еще придерживаются этого предположения, я провел тест, который доказывает обратное:

class B
{
public:
    B()
    {
        cout << "B constructor" << endl;
    }
};

class A : public B
{
public:
    A()
    {
        cout << "A constructor" << endl;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    A a;
    return 0;
}

// вывод из VS2008

B constructor
A constructor
Press any key to continue . . .

Ответы [ 5 ]

22 голосов
/ 25 апреля 2011

Конструктор базового класса вызывается в обоих случаях.

Вот ссылка на статью с дополнительной информацией.

7 голосов
/ 25 апреля 2011

Если конструктор базового класса не принимает никаких аргументов, то явное упоминание о нем в списке инициализации не требуется.

5 голосов
/ 25 апреля 2011

Чтобы завершить учебный процесс и развить более глубокое понимание, вы можете начать слегка изменять вещи.Например, что происходит, когда B не имеет конструктора по умолчанию?Это даже компилируется?Другие небольшие модификации, такие как эта, обеспечат большой опыт обучения.

Тем не менее, по моему опыту, лучше сделать это

A::A() : B() { ... } 

, чем

A::A() { ... } 

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

4 голосов
/ 25 апреля 2011

Если B не имеет объявленного пользователем конструктора, поведение будет другим. Сравните:

struct SimpleAggregate {
  int a;
  float b;
};

struct ClassWrapper : SimpleAggregate {
  ClassWrapper() : SimpleAggregate() { }
};

ClassWrapper w;

Теперь w.a и w.b гарантированно равны нулю. Если бы вы прекратили явную инициализацию базового класса, они бы имели неопределенные значения.


Вам может быть неизвестно, что, несмотря на синтаксис, приведенное выше использование SimpleAggregate() не не вызывает конструктор по умолчанию. Это просто значение инициализирует базовый класс (у нас есть несколько хороших ответов здесь, в Stackoverflow о том, что такое «инициализация значения»), не вызывая конструктор по умолчанию, потому что пользователь не объявлен.

2 голосов
/ 25 апреля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...