How the compilers implement the virtual inheritance?
In the following code:
class A {
public:
A(int) {}
};
class B : public virtual A {
public:
B() : A(1) {}
};
class C : public B {
public:
C() : A(3), B() {}
};
Does a compiler generate two instance of B::ctor
function, one without A(1)
call, and one with it? So when B::constructor
is called from derived class's constructor the first instance is used, otherwise the second.
As mentioned before, it depends on the compiler implementation.
But, usually each time a programmer adds a new method, is stored in code, even if there is another method with the same id. elsewhere ("overriden" or "overloaded").
The code for each method is stored only once, so if a class inherits and uses the same method from a parent class, internally, its uses a pointer to the code, it doesn't duplicates the code.
If a parent class defines a virtual method, and if a child class overrides it, both methods are stored. Each class has something called "Virtual Method Table" where there is a table of pointers to each method.
Don't worry about performance, the compiler doesn't duplicate code for methods.
The compiler does not create another constructor of B - but it ignores the
A(1)
. SinceA
is virtually inherited, it is constructed first, with its default constructor. And since it's already constructed whenB()
is invoked, theA(1)
part is ignored.Edit - I missed the
A(3)
part inC
's constructor initialization list. When virtual inheritance is used, only the most derived class initializes the virtual base classes. SoA
will be constructed withA(3)
and not its default constructor. The rest still stands - any initializations ofA
by an intermediate class (hereB
) are ignored.Edit 2, trying to answer the actual question regarding the implementation of the above:
In Visual Studio (at least 2010), a flag is used instead of having two implementations of
B()
. SinceB
virtually inherits fromA
, before it callsA
's constructor, the flag is checked. If the flag is not set, the call toA()
is skipped. Then, in every class deriving fromB
, the flag is reset after it initializesA
. The same mechanism is used to preventC
from initializingA
if it's part of someD
(ifD
inherits fromC
,D
will initializeA
).The Itanium C++ ABI is a useful resource for all questions like "how could this be implemented by C++ compilers".
In particular 5.1.4 Other Special Functions and Entities list different special member functions for different purposes:
The 1.1 Definitions section is useful (but not complete):
From these definitions, the purpose of the complete object constructor and of the base object constructor are obvious.
I suggest you to read some papers. These two are really interesting, especially the first since it comes from C++'s father:
[1] Bjarne Stroustrup. Multiple Inheritance for C++. The C/C++ Users Journal, May 1999.
[2] J. Templ. A Systematic Approach to Multiple Inheritance Implementation. ACM SIGPLAN Notices, Volume 28, No. 4 April 1993.
I used them as main references while making a seminar (as a student) on multiple inheritance in my university.
It's implementation-dependent. GCC (see this question), for example, will emit two constructors, one with a call to
A(1)
, another one without.When B is constructed, the "full" version is called:
When C is constructed, the base version is called instead:
In fact, two constructors will be emitted even if there is no virtual inheritance, and they will be identical.