简体   繁体   中英

Constructor call in inherited classes

Consider the following code:

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();

}

And its output -- program compiled with g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3:

B[0]

B[-2097962768]
C[-2097962768]

The only way I found to get the second call -- C() -- to have its values initialized was adding an explicit call to the constructors, like:

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; }
};

Although I understand that calling the default constructor of each former class will initialize the values, I'm not able to see what is being called when nothing is specified.

Isn't the default constructor what is called by default -- hence its handle?

With your original code

class A {
public:
    int a;
};

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

the members of A are not initialized, because you have not specified any initialization. And generally, in C++ you don't pay for what you don't need. So, you don't get initialization by default for POD members (however, you do get it for members that have constructors, because there the initialization is specified).

In your subsequent "explicit constructor call" code

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

you have specified value initialization of the A base class sub-object. Effectively this reduces to zero-initialization.

It's the same difference as

A* p = new A;

versus

A* p = new A();

The latter value-initializes the object.


Standardese…

C++11 §8.5/10 :
“An object whose initializer is an empty set of parentheses, ie, () , shall be value-initialized.”

C++11 §8.5./7 :
“To value-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T's implicitly-declared default constructor is non-trivial, that constructor is called.
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized.
An object that is value-initialized is deemed to be constructed and thus subject to provisions of this International Standard applying to “constructed” objects, objects “for which the constructor has completed,” etc., even if no constructor is invoked for the object's initialization.”

It is perhaps worth noting that value initialization was not part of the original C++98. It was introduced in C++03, by Andrew Koenig (of "Koenig look-up" fame) in order to deal with some severe problems of unexpected effects of pure default-initialization. Which is what the () initializer bought you in C++98.

Edit my original answer was quite wrong, so I have edited it heavily.

If you want to guarantee that A::a is zero-initialized in the absence of value initialization calls such as

A a1; //

or

B() { .... }

then you can give A a constructor and do the initialization there:

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

Otherwise, explicitly calling A() in B and C 's constructors performs the value initialization.

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

This also works for initialization of an A instance:

A a1 = A();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM