Order of constructor call in virtual inheritance

2020-01-27 06:58发布

class A {
        int i;
public: 
        A() {cout<<"in A's def const\n";};
        A(int k) {cout<<"In A const\n";  i = k; }
        };

class B : virtual public A {
public:
        B(){cout<<"in B's def const\n";};
        B(int i) : A(i) {cout<<"in B const\n";}
        };

class C :   public B {
public:
        C() {cout<<"in C def cstr\n";}
        C(int i) : B(i) {cout<<"in C const\n";}
        };

int main()
{
        C c(2);
        return 0;
}

The output in this case is

in A's def const
in B const
in C const

Why is this not entering into in A const

`It should follow the order of 1 arg constructor call. But what actually is happening on deriving B from A using virtual keyword.

There are few more question

Even if I remove the virtual keyword in above program and remove all the default constructor it gives error. So, why it needs the def constructor

3条回答
兄弟一词,经得起流年.
2楼-- · 2020-01-27 07:34

As JamesKanze has explained, in case of virtual inheritance it is the most derived class that calls the virtual base class' constructor. So, if you want A's constructor that takes an integer to be called, you need to add that to C's initialization list.

C(int i) : A(i), B(i) {cout<<"in C const\n";}

For the second part of your question, default constructors are not required, but then the derived class must call the non-default constructor explicitly, since the compiler is unable to do that for you in the absence of a non-default constructor.

#include <iostream>
using namespace std;

class A {
  int i;
public:
  // A() {cout<<"in A's def const\n";};
  A(int k) {cout<<"In A const\n";  i = k; }
};

class B : virtual public A {
public:
  // B(){cout<<"in B's def const\n";};
  B(int i) : A(i) {cout<<"in B const\n";}
};

class C :   public B {
public:
  C() : A(42), B(42) {cout<<"in C def cstr\n";}
  C(int i) : A(i), B(i) {cout<<"in C const\n";}
};

int main()
{
  C c(2), c2;
  return 0;
}

This prints out

In A const
in B const
in C const
In A const
in B const
in C def cstr
查看更多
女痞
3楼-- · 2020-01-27 07:44

There are two questions here.

Why is this not entering into in A const?

Because you are using virtual inheritance.

When you use virtual inheritance, the Initialization list of most-derived-class's ctor directly invokes the virtual base class's ctor.. In this case, that means that C's constructor calls A's constructor directly. Since you have not specified which A constructor to call in C's initialization list, the default constructor is called.

This is fixed by changing your implementation of C::C(int) to:

C(int i) : A(i), B(i) {cout<<"in C const\n";}

If I remove the virtual keyword in above program and remove all the default constructor it gives error. So, why it needs the def constructor?

Because B also doesn't specify which A ctor to call, so the default constructor is used. If you remove As def ctor, B can't be compiled.

查看更多
闹够了就滚
4楼-- · 2020-01-27 07:56

The constructors for virtual base classes are always called from the most derived class, using any arguments it might pass in. In your case, the most derived class doesn't specify an initializer for A, so the default constructor is used.

查看更多
登录 后发表回答