There was a question on the subject of multiple inheritance in C ++. Suppose we have some code, which is a case of diamond-shaped inheritance, in which class A is a virtual base class for classes B and C , which, in turn, are basic for class D :

#include <iostream> class A { public: int a; public: A() : a(0) {} A(int _a) : a(_a) {} }; class B : virtual public A { public: int b; public: B(int _a, int _b) : A(_a), b(_b) {} }; class C : virtual public A { public: int c; public: C(int _a, int _c) : A(_a), c(_c) {} }; class D : public B, public C { public: int d; public: D(int _a, int _b, int _c, int _d) : B(_a, _b), C(_a, _c), d(_d) {} }; int main() { D obj(1, 2, 3, 4); std::cout << "obj.a = " << obj.a << std::endl; // Выводит: 0 std::cout << "obj.b = " << obj.b << std::endl; // Выводит: 2 std::cout << "obj.c = " << obj.c << std::endl; // Выводит: 3 std::cout << "obj.d = " << obj.d << std::endl; // Выводит: 4 return 0; } 

It is clear that the presence of a virtual base class A ensures that when constructing an object of type D we will have only one copy of a subobject of class A. This leads to a completely different behavior, different from if the base class were not virtual. The results of the executed code show that creating a single instance of a sub-class A subobject is the default constructor in class A , and its call occurs in the constructor of class D through the initialization list, and not in the immediate descendants B and C , which directly inherit from A. It is clear that instead of generating a default constructor for the exporter to be exported, you can explicitly indicate any other class A constructor in the class D constructor initialization list.

The question is the following: calling constructors B(_a, _b) and C(_a, _c) immediate ancestor classes of class D , we must come to the chain to explicitly call the constructor of class A in the initialization lists of class B and class C , but this does not happen in the presence of a virtual base class. It turns out the initialization code A(_a) in the constructors of the B and C classes is simply ignored by the compiler and can be safely removed without changing the behavior?

  • You can remove it, but will it not spoil this behavior in other cases? - VladD

1 answer 1

You can remove how far it will be painless to say in your abstract case is not realistic.

And by the way, your class A not virtual, since there are no virtual members of functions and a _vptr pointer to vtable , etc. etc.

Due to the virtual inheritance of classes B and C from A , class D directly inherits A , and not through B and С to avoid duplicate copies of object А in D - therefore, if you explicitly call the parameterized constructor А in D , then you will output 1, 2, 3 , four.

Ie virtual inheritance guarantees direct inheritance without intermediate ancestors, which in turn provides only one copy of the ancestor in the heir.

  • Are virtual member functions and virtual classes not different concepts? It seems to me that the virtuality of the class determines how the base class object will be constructed as part of the derived class object. And it doesn’t matter if there are virtual functions in the base class. These are things that are independent of each other. Or is it all wrong? - Dmitriy
  • you need to conceptually understand the question, and not grind some abstract things) - ampawd