Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ladder-like C++ virtual inheritance

If I have a class inheritance relation like the following

               a
              /  \
             b    c
              \   |
               |  d
                \/ \
                e   f
                 \ /
                  g

Is the following the correct definition?

    class A {};
    class B: public virtual A {};
    class C: public virtual A {};
    class D: public C {};
    class E: public B, public virtual D  {};
    class F: public virtual D {};
    class G: public E, public F {};

I made both A and D virtually inherited because I assume each joint class need to be virtual.

Also I am not sure how C++ defines the constructor order of the above case. The link https://isocpp.org/wiki/faq/multiple-inheritance#mi-vi-ctor-order says

The very first constructors to be executed are the virtual base classes anywhere in the hierarchy. They are executed in the order they appear in a depth-first left-to-right traversal of the graph of base classes, where left to right refer to the order of appearance of base class names.

After all virtual base class constructors are finished, the construction order is generally from base class to derived class. The details are easiest to understand if you imagine that the very first thing the compiler does in the derived class’s ctor is to make a hidden call to the ctors of its non-virtual base classes (hint: that’s the way many compilers actually do it). So if class D inherits multiply from B1 and B2, the constructor for B1 executes first, then the constructor for B2, then the constructor for D. This rule is applied recursively; for example, if B1 inherits from B1a and B1b, and B2 inherits from B2a and B2b, then the final order is B1a, B1b, B1, B2a, B2b, B2, D.

Note that the order B1 and then B2 (or B1a then B1b) is determined by the order that the base classes appear in the declaration of the class, not in the order that the initializer appears in the derived class’s initialization list.

If so, is the order like?

  A, D, B, C, D, F, G

I do not expect D is constructed before C. What is the correct constructor order?

like image 248
Joe C Avatar asked Mar 27 '18 04:03

Joe C


2 Answers

When constructing an object of class G, the virtual base classes are initialized first. This results in the constructors for A and D being called. The constructor for D will construct it's base C object. Then the constructors for the non-base classes of G will be called, which would be E and F. The constructor for E will call the constructor for B. This gives the final order:

A C D B E F G
like image 115
1201ProgramAlarm Avatar answered Oct 30 '22 00:10

1201ProgramAlarm


I added constructors that call printf to watch what happens (code available on Godbolt for the curious). The order I got, with both clang (version 6.0.0) and gcc (versions 6.4.0 and 7.3.0), is:

A
C
D
B
E
F
G

This matches what I'd expect. A and D have to be constructed first, but you can't construct a D without a C (imagine a more complex example where D's constructor called into C. Once all virtual inheritance has been satisfied, the constructors are called in the same order we expect.

like image 41
Stephen Newell Avatar answered Oct 30 '22 02:10

Stephen Newell