1

I've known that if B is derived from A, then when I create a new object of B, for example b, the constructor of A will call first. When I destroy the object b, The destructor of B will call first. Then I have a question here, if there're more than one constructor in the Base class, which constructor will call ? and why?

I've write one test program below, I guess it will call the default constructor in the Base class, But I'm not sure if it is just a coincidence?

#include <iostream>
using namespace std;

class A{
    public:
    A(int i){cout<<"A con with param"<<endl;}
    A(){cout<<"A con"<<endl;}
    ~A(){}
};

class B : public A
{
    public:
    B(int i){cout<<"B con with param"<<endl;}
    B(){cout<<"B con"<<endl;}
    ~B(){}
};

int main()
{
    B b(5);
    return 0;
}

I wonder if any boss can tell me the reason or any advise to figure out this problem?

  • In your example, `A()` would always be called from your `B` constructors, because you didn't specify for them to call anything but `A`'s empty constructor (which takes no arguments). Similar questions: http://stackoverflow.com/questions/8093882/using-c-base-class-constructors or http://stackoverflow.com/questions/10001524/how-to-force-base-class-constructors-to-be-called-in-derived-classes – wkl May 10 '12 at 13:01

4 Answers4

3

If you write:

B(int i) { cout<<"B con with param"<<endl; }

then constructor A() (without arguments) will be called.

If you write:

B(int i): A(i) { cout<<"B con with param"<<endl; }

then constructor A(int) will be called.

Pavel Strakhov
  • 39,123
  • 5
  • 88
  • 127
  • Oh, I got it! The selection of base class constructor is decided in the constructor initializer list of derived class, If I don't specify, it will call the default constructor of the Base class, right? – struggling on the way May 10 '12 at 13:16
1

Nothing is by coincidence in programming.
The default constructor is called because, you did not pass int argument explicitly to base class.

For other constructor of base class to be called, the derived class constructor needs to pass the parameters to base class constructor.
So for A(int) to be called, you need to have B():A(some_int) or B(int):A(some_int)

Vinayak Garg
  • 6,518
  • 10
  • 53
  • 80
0

The empty constructor of the parent class will be called unless you call some other constructor explicitly in the initializer list.

EDIT: here is how you call constructor explicitly:

B(int i) : A(i) {
  ... do stuff ...
}
Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
0

The order of initialization is a bit more convoluted than that. Technically it starts in the initialization list of the most derived object. That constructor is selected with regular overload resolution from the location where the object is being created. The initialization list of the most derived type constructor lists (either explicitly or implicitly) the constructors of the bases, and again the constructor of the bases will be selected using overload resolution on the call in the initialization list. If the base is not explicitly stated in the initialization list, the compiler will inject a call to the default constructor.

The exact order of construction is also a bit more complex in that the first subobjects that are initialized are the virtual bases, in a particular order (depth-first, left-to-right where left-to-right is the order of declaration in the base classes declaration). Once all virtual bases are initialized, then the direct non-virtual bases of the most derived type are initialized, again in the order of declaration (left-to-right). Once all bases are initialized, the members are then initialized in the order of declaration in the class.

Note that in all cases, the code can explicitly list the subobject in the initialization list, and the constructor listed there will be used, or the default constructor if the entity is not listed.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489