user2076774
user2076774

Reputation: 405

Inheritance, why do two constructors get called for base class, C++

I am trying to do an assignment in my book but I do not understand the output. When the main code in the program is run the output is:

B::B(3)

B::B() //why is this outputted

B::B(-3)

D::D(3)

It gets this from calling B::B(int n) {} first and then B::B() {} followed by the the next two lines which I get. So the program called the first one since it is declared as the constructor the class A in the function and it has to assign values, what I dont get is output line 2, why is B::B() {} even called? it gets called as a constructor but shouldnt just the constructor with parameters get called?

class B {
public:
    B(); //why is this  called?
    B(int n);
};

// Definitions of B
B::B() { 
    cout << "B::B()\n";
}
B::B(int n) {
    cout << "B::B(" << n << ")\n";
}

class D : public B {
public:
    D();
    D(int n);
private:
    B b;
};

// Definitions of D
D::D() {
    cout << "D::D()\n";
}
D::D(int n) : B(n) {
    b = B(-n);
    cout << "D::D("<< n <<")\n";
}

int main(int argc, const char * argv[]) {
    // insert code here...

    D d(3);
    return 0;    
}

Upvotes: 0

Views: 170

Answers (2)

Pixelchemist
Pixelchemist

Reputation: 24966

Your class D contains two objects of type B.

  1. the implicit B from inheritance
  2. the explicit B member named b

You could rewrite the constructor

D::D(int n) : B(n)
{
    b = B(-n);
    cout << "D::D("<< n <<")\n";
}

like

D::D(int n) : B(n), b()
{
    b = B(-n);
    cout << "D::D("<< n <<")\n";
}

where it is apparent where the B::B() comes from. Thus your output is easily explained:

B::B(3) // base constructor of `D`
B::B() // default construction of `b` member
B::B(-3) // explicit construction inside D::D(int)
D::D(3) // D::D(int)

If you write

D::D(int n) : B(n), b(-n)
{
    cout << "D::D("<< n <<")\n";
}

instead, there is only

B::B(3)
B::B(-3)
D::D(3)

left.

Addressing the comment:

Imagine D to look like:

class D : public B
{
public:
  D(int);
};

with the constructor definition

D::D(int v) { std::cout << "foo with " << v; }

then, the code

D d(3);

prints

B::B()
foo with 3

and it is perfectly valid as long as B is default constructible.

If B would lack a default constructor you'd get a compiler error and you'd want to rewrite the definition of D to

D::D(int v) : B(3) { std::cout << "foo with " << v; }

Every direct base class or member that is not part of the constructors initializer list is default constructed (in case of a class type) or left uninitialized in case of a fundamental type.

Upvotes: 0

First the base class constructor is called: B::B(3).
Then the constructor for the b field is called: B::B().
Then the derived constructor body is executed (after all fields are constructed).
D's constructor first constructs another B on the line b = B(-n); (so B::B(-3) is printed), then prints D::D(3).

Upvotes: 3

Related Questions