Вызов конструктора в унаследованных классах

Рассмотрим следующий код:

class A {
public:
int a;
};

class B : public A {
public:
B() { std::cout << "B[" << a << "]" << std::endl; }
};

class C : public B {
public:
C() { std::cout << "C[" << a << "]" << std::endl; }
};

int main(int argc, char *argv[]) {

B();
std::cout << std::endl;
C();

}

И ее вывод — программа, скомпилированная с g ++ (Ubuntu / Linaro 4.6.3-1ubuntu5) 4.6.3:

B[0]

B[-2097962768]
C[-2097962768]

Единственный способ найти второй звонок — C() — чтобы его значения инициализировались, добавлялся явный вызов конструкторам, например:

class B : public A {
public:
B() : A() { std::cout << "B[" << a << "]" << std::endl; }
};

class C : public B {
public:
C() : B() { std::cout << "C[" << a << "]" << std::endl; }
};

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

Разве конструктор по умолчанию не вызывается по умолчанию — отсюда его дескриптор?

2

Решение

С вашим оригинальным кодом

class A {
public:
int a;
};

class B : public A {
public:
B() { std::cout << "B[" << a << "]" << std::endl; }
};

члены A не инициализированы, потому что вы не указали никакой инициализации. И вообще, в C ++ вы не платите за то, что вам не нужно. Таким образом, вы не получаете инициализацию по умолчанию для членов POD (однако вы получаете ее для членов, которые имеют конструкторы, потому что там указана инициализация).

В последующем коде «явный вызов конструктора»

class B : public A {
public:
B() : A() { std::cout << "B[" << a << "]" << std::endl; }
};

вы указали инициализация значения из A подобъект базового класса. Фактически это сводится к нулевой инициализации.

Это такая же разница, как

A* p = new A;

против

A* p = new A();

Последнее значение — инициализирует объект.


Standardese …

C ++ 11 §8.5 / 10:
«Объект, инициализатором которого является пустой набор скобок, то есть (), должен быть инициализирован значением. »

C ++ 11 §8.5. / 7:
«Для того, чтобы Значение инициализации объект типа T средства:
— если T является (возможно, cv-квалифицированным) типом класса (раздел 9) с предоставленным пользователем конструктором (12.1), тогда конструктором по умолчанию для T называется (и инициализация плохо сформирована, если T не имеет доступного конструктора по умолчанию);
— если T является (возможно, cv-квалифицированным) типом класса, не содержащим объединение, без предоставленного пользователем конструктора, тогда объект инициализируется нулями, и, если неявно объявленный конструктор T по умолчанию является нетривиальным, вызывается этот конструктор.
— если T тип массива, тогда каждый элемент инициализируется значением;
— иначе объект инициализируется нулями.
Объект, инициализированный значением, считается созданным и, таким образом, подпадает под действие положений настоящего международного стандарта, применяемых к «построенным» объектам, объектам, «для которых конструктор завершен» и т. Д., Даже если для объекта не вызывается конструктор. инициализация «.

Возможно, стоит отметить, что инициализация значения не была частью оригинального C ++ 98. Он был введен в C ++ 03 Эндрю Кенигом (из известности «поиск Кенига»), чтобы иметь дело с некоторыми серьезными проблемами неожиданных эффектов чистой инициализации по умолчанию. Что есть то, что () инициализатор купил тебя в C ++ 98.

6

Другие решения

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

Если вы хотите гарантировать, что A::a инициализируется нулем при отсутствии вызовов инициализации значения, таких как

A a1; //

или же

B() { .... }

тогда вы можете дать A конструктор и сделайте инициализацию там:

class A {
public:
A() : a() {} // value initialization of a, means zero initialization here.
int a;
};

В противном случае явно A() в B а также CКонструкторы выполняют инициализацию значения.

// value initialization of A sub-object leads to zero initialization of A::a
B() : A() {}

Это также работает для инициализации A пример:

A a1 = A();
3

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector