Last chapter, in lesson 17.9 -- Multiple inheritance, we left off talking about the “diamond problem”. In this section, we will resume this discussion.
Note: This section is an advanced topic and can be skipped or skimmed if desired.
The diamond problem
Here is our example from the previous lesson (with some constructors) illustrating the diamond problem:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
class PoweredDevice { public: PoweredDevice(int power) { std::cout << "PoweredDevice: " << power << '\n'; } }; class Scanner: public PoweredDevice { public: Scanner(int scanner, int power) : PoweredDevice{ power } { std::cout << "Scanner: " << scanner << '\n'; } }; class Printer: public PoweredDevice { public: Printer(int printer, int power) : PoweredDevice{ power } { std::cout << "Printer: " << printer << '\n'; } }; class Copier: public Scanner, public Printer { public: Copier(int scanner, int printer, int power) : Scanner{ scanner, power }, Printer{ printer, power } { } }; |
Although you might expect to get an inheritance diagram that looks like this:
If you were to create a Copier class object, by default you would end up with two copies of the PoweredDevice class -- one from Printer, and one from Scanner. This has the following structure:
We can create a short example that will show this in action:
1 2 3 4 5 6 |
int main() { Copier copier{ 1, 2, 3 }; return 0; } |
This produces the result:
PoweredDevice: 3 Scanner: 1 PoweredDevice: 3 Printer: 2
As you can see, PoweredDevice got constructed twice.
While this is often desired, other times you may want only one copy of PoweredDevice to be shared by both Scanner and Printer.
Virtual base classes
To share a base class, simply insert the “virtual” keyword in the inheritance list of the derived class. This creates what is called a virtual base class, which means there is only one base object. The base object is shared between all objects in the inheritance tree and it is only constructed once. Here is an example (without constructors for simplicity) showing how to use the virtual keyword to create a shared base class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class PoweredDevice { }; class Scanner: virtual public PoweredDevice { }; class Printer: virtual public PoweredDevice { }; class Copier: public Scanner, public Printer { }; |
Now, when you create a Copier class object, you will get only one copy of PoweredDevice per Copier that will be shared by both Scanner and Printer.
However, this leads to one more problem: if Scanner and Printer share a PoweredDevice base class, who is responsible for creating it? The answer, as it turns out, is Copier. The Copier constructor is responsible for creating PoweredDevice. Consequently, this is one time when Copier is allowed to call a non-immediate-parent constructor directly:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#include <iostream> class PoweredDevice { public: PoweredDevice(int power) { std::cout << "PoweredDevice: " << power << '\n'; } }; class Scanner: virtual public PoweredDevice // note: PoweredDevice is now a virtual base class { public: Scanner(int scanner, int power) : PoweredDevice{ power } // this line is required to create Scanner objects, but ignored in this case { std::cout << "Scanner: " << scanner << '\n'; } }; class Printer: virtual public PoweredDevice // note: PoweredDevice is now a virtual base class { public: Printer(int printer, int power) : PoweredDevice{ power } // this line is required to create Printer objects, but ignored in this case { std::cout << "Printer: " << printer << '\n'; } }; class Copier: public Scanner, public Printer { public: Copier(int scanner, int printer, int power) : PoweredDevice{ power }, // PoweredDevice is constructed here Scanner{ scanner, power }, Printer{ printer, power } { } }; |
This time, our previous example:
1 2 3 4 5 6 |
int main() { Copier copier{ 1, 2, 3 }; return 0; } |
produces the result:
PoweredDevice: 3 Scanner: 1 Printer: 2
As you can see, PoweredDevice only gets constructed once.
There are a few details that we would be remiss if we did not mention.
First, virtual base classes are always created before non-virtual base classes, which ensures all bases get created before their derived classes.
Second, note that the Scanner and Printer constructors still have calls to the PoweredDevice constructor. When creating an instance of Copier, these constructor calls are simply ignored because Copier is responsible for creating the PoweredDevice, not Scanner or Printer. However, if we were to create an instance of Scanner or Printer, those constructor calls would be used, and normal inheritance rules apply.
Third, if a class inherits one or more classes that have virtual parents, the most derived class is responsible for constructing the virtual base class. In this case, Copier inherits Printer and Scanner, both of which have a PoweredDevice virtual base class. Copier, the most derived class, is responsible for creation of PoweredDevice. Note that this is true even in a single inheritance case: if Copier was singly inherited from Printer, and Printer was virtually inherited from PoweredDevice, Copier is still responsible for creating PoweredDevice.
Fourth, all classes inheriting a virtual base class will have a virtual table, even if they would normally not have one otherwise, and thus be larger by a pointer.
Because Scanner and Printer derive virtually from PoweredDevice, Copier will only be one PoweredDevice subobject. Scanner and Printer both need to know how to find that single PoweredDevice subobject, so they can access its members (because after all, they are derived from it). This is typically done through some virtual table magic (which essentially stores the offset from each subclass to the PoweredDevice subobject).
![]() |
![]() |
![]() |
when does virtual base class is implemented in c++ program
I don't understand what you are trying to ask. Can you rephrase?
Hey Alex,
I didn't understood the fourth point completely.
what did you mean by
"But classes inheriting the virtual base still need access to it. So in order to facilitate this, the compiler creates a virtual table for each class directly inheriting the virtual class (Printer and Scanner). These virtual tables point to the functions in the most derived class."
does this mean that the virtual table of the printer and scanner will point to Copier's functions
Because PoweredDevice is a virtual base class, it's considered a direct base of Copier (as are Printer and Scanner). But Printer and Scanner also need access to PoweredDevice (because they are derived from it too).
To make this work, the compiler creates virtual tables for Printer and Scanner, and these tables point to the most derived functions in Copier. So yes.
"While this is often desired, other times you may want only one copy of PoweredDevice to be shared by both Scanner and Printer."
What are some pros and cons of both? I can't think of any, except making only one copy sounds to me like it would be quicker/more efficient, but that would, I feel, shift the desireability greatly towards making only one copy. On the other hand, writing a virtual class seems more complex, so it might just be a tradeoff between the efficiency of writing the code and the efficiency of running the code. I can't think of any other reasons either of the two would be desireable over one another, but that's probably the lack of experience on my part!
It really depends on how you want to model the objects.
Let's say that a PoweredDevice contains a member indicating whether the device uses AC or DC power. If you have a device that is both a Scanner and a Printer, it probably only uses one source of power, and therefore should contain one PoweredDevice, not two. Otherwise you end up with multiple sources of the same data that can get out of sync.
However, let's say that PoweredDevice instead contains a manufacturer ID. If you have a device that is both a Scanner and a Printer, both the Scanner and the Printer probably have different manufacturer IDs, so it may be more appropriate for each of have their own PoweredDevice.
Explain this More Clearly, Please !
-> "Fourth, a virtual base class is always considered a direct base of its most derived class (which is why the most derived class is responsible for its construction). But classes inheriting the virtual base still need access to it. So in order to facilitate this, the compiler creates a virtual table for each class directly inheriting the virtual class (Printer and Scanner). These virtual tables point to the functions in the most derived class. Because the derived classes have a virtual table, that also means they are now larger by a pointer (to the virtual table)."
And,
In the 1st point which says" Virtual Base Classes are Created Before Non-Virtual Ones", How does the compiler know about it, It just does it's work of creating things sequentially (from the start of the program).
Help Please !
Thanks In Advance, Alex ! :)
There's a lot in that first paragraph. What do you need explained in more detail?
The compiler knows which classes are virtual base classes and which are not. Normally it calls base constructors in order, but in this case, it will call virtual base constructors before non-virtual ones, even if they are out of order in the constructor's initializer list.
Mainly This :-
" So in order to facilitate this, the compiler creates a virtual table for each class directly inheriting the virtual class (Printer and Scanner). These virtual tables point to the functions in the most derived class. Because the derived classes have a virtual table, that also means they are now larger by a pointer (to the virtual table)."
I want to clarify something:-
Compiler starts from the start of the program,No? Actually my Maam said think compilation start from main() which i guess is absolutely wrong ! Whats your Take, Anyways?
Thanks in advance ;)
The main point of that first paragraph was to indicate that a virtual table is set up for each class directly inheriting the virtual class, even if no virtual functions are used. For more information on why, see the first answer.
Compilation goes through each code (.cpp) file in sequence, top to bottom. Runtime starts at main().
exactly what i said to my maam but you know it man ! :(
how this line is ignored?
It is not executed because in this case, Copier (the most derived class) is responsible for initialization of PoweredDevice.
Great tutorial.
At the end of the article you have mentioned 4 points. I am not able to understand the 4th point. I am aware of virtual table. You have said
" But classes inheriting the virtual base still need access to it. So in order to facilitate this, the compiler creates a virtual table for each class directly inheriting the virtual class (Printer and Scanner). "
I am not sure how vtable in Copier helps Printer and Scanner in accessing the virtual base class. Could you please explain that ?
Thanks
Hi Alex,
Typo found again 030
"Here is an example (without constructors for simplicity) showing how to use to virtual keyword to create a shared base class:"
Did you mean "to use the virtual keyword"
Yes. Fixed. Thanks for pointing that out.
Typo. In the last sentence before the first code snippet showing the "virtual" keyword in action, you wrote:
" Here is the an example..."
Fixed, thanks!
2 questions
1- If there is CopierTwo class which is derived from Copier class, which of them is responsible of constructing PoweredDevice ?
In case Copier object created in the main function, then Copier can and responsible for constructing PoweredDevic ? I think this is logical but
Similarly, in case CopierTwo object created in the main function, then CopierTwo can and responsible for constructing PoweredDevic & Copier ? or only Copier (and Copier constructs PoweredDevic?)
2- When you said "First, virtual base classes are created before non-virtual base classes, which ensures all bases get created before their derived classes.", what do you mean in context of the last example mentioned.
Do you mean PoweredDevice is constructed first then Printer and Scanner ?
or Printer and Scanner first then PoweredDevice ?
I'm confused on this number 2 question since the last example output is
PoweredDevice: 3
Scanner: 1
Printer: 2
which means PoweredDevice is constructed first in the "normal" chain construction of inheritance tree. Copier constructor hold > Printer constructor hold & Scanner constructor hold > PoweredDevice constructor execute > Printer constructor execute & Scanner constructor execute > Copier constructor execute.
Maybe I'm getting it wrong and you actually talking about something else (like if there is third class on Printer & Scanner level but it inherits non-virtual PoweredDevice) So what you meant exactly by this please ?
1) Both Copier and CopierTwo need to be responsible for constructing PoweredDevice.
2) Copier is responsible for creating Printer, Scanner, and PoweredDevice. Because virtual base classes are always created first, PoweredDevice gets created before Printer and Scanner, just in case PoweredDevice initializes something that Printer or Scanner need.
Edit: Answer updated after Anddo responded.
1) it seems if I created CopierTwo then I have to explicitly call the base class. Here is what I tried
So I guess whenever there is virtual inheritance in the chain, I have to explicitly call the base class constructor from ANY/ALL derivatives, no matter how deep they are ?
2) Got that :)
Another additional question
3) I tried to make class inherits 3 classes which are only 2 of them have virtual inheritance to base class and the third one has normal inheritance to base class. On XCode, this appears to create two objects of the base class, while on Visual studio I get the error (ambiguous access of 'A'). Here is the code
Output of XCode is
----------------------
A is called and val = 5
C is called
B is called
A is called and val = 4
D is called
E is called
Program ended with exit code: 0
----------------------
So is this a bug or certain limitation in VS compiler or something ? Any explanation would much appreciated.
As always, thanks for answering and for your great tutorials :)
1) Yes, it appears you are correct. I had thought only Copier needed to create PoweredDevice(), and that CopierTwo could rely on Copier to create the PoweredDevice(). But it appears C++ isn't that smart (yet), so both Copier and all classes derived from Copier need to create the PoweredDevice class.
C++ has this to say:
So most-derived classes have special rules to make virtual base classing work.
3) This is a very interesting question. I'm not sure what the C++ standard has to say about this behavior, or how to resolve it. It looks like XCode is making a (reasonable) assumption that because your most-derived class is trying to call the base class constructor directly, it must be trying to access the virtual base class (as calling the non-virtual base class constructor directly would be illegal). Visual Studio isn't making this distinction.
I do note that in Visual Studio you can resolve this ambiguity like this:
Surprisingly, the following also compiles in visual studio 2015:
Though it doesn't do what you'd expect: virtual base class A is still initialized with value 5, even though it looks like we're specifying D's non-virtual version of A() to initialize (which would be illegal, as it is a non-immediate base class through this path).
IMO, this is probably a bug in Visual Studio, and XCode is probably handling this more correctly.
The syntax is essentially the same when referring to the member of an instantiated object.
Say A has a member int m_x. You want to refer to m_x, but E inherits multiple m_x's, because it contains multiple A's. You have to let the compiler know which one you're referring to.
Instantiate an E object:
E instance;
instance.B::A::m_x; // This refers to the m_x inherited through B
instance.C::A::m_x; // This refers to the m_x inherited through C
instance.D::A::m_x; // This refers to the m_x inherited through D
(note that A was inherited virtually through B & C, so the B & C m_x is actually the same member, whereas the one inherited via D is a separate int))
Even though m_x lives in A, it's inherited through B or C, so just specifying B or C in the scope operator, without mentioning A, is enough to resolve the ambiguity:
instance.B::m_x; // This refers to the m_x inherited through B
instance.C::m_x; // This refers to the m_x inherited through C
instance.D::m_x; // This refers to the m_x inherited through D
(Again, note that A was inherited virtually through B & C, so the B & C m_x is actually the same member, whereas the one inherited via D is a separate int)
In case we don't call the PoweredDevice's constructor from list of Copier constructor while still declaring it as virtual, would it still work ?
Would the Scanner and Printer class then create the PoweredDevice object?
No. If PoweredDevice had a default constructor, that would get used. If it didn't, you get an error about no appropriate constructor found for PoweredDevice.
Thank you very much for the tutorials!
I have a question on a very edge case (as protected/private inheritance is rare enough without also involving multiple inheritance):
What happens if the two parent classes inherit the base differently (e.g. Scanner inherits privately rather than publicly)?
My thoughts:
Since the most derived class is responsible for constructing the base, it seems like the base is acting as a temporary (or virtual?) parent. In this case, then all three of the inherited classes could be considered equal base classes for Copier. Is this what you meant on your first point, when you say that virtual base classes are constructed before non-virtual base classes?
If this is the case, then there is no way to specify inheritance from the virtual base. In this case, does it default to public (rather than private)?
I wasn't sure, so I had to do some experimentation. The most derived class can access the virtual base class so long as at least one of the derived classes provides an access path. So in the lesson example, if we made Scanner private, Copier could still access the members of PoweredDevice through Printer.
"multiple inheritance" link at the top of the page points to this page. It should point to previous section being 11.7.
What happens if one of the base classes, that is, printer or scanner is derived as virtual and the other is not. Now, if we create an instance of copier, which one is responsible to call the constructor of powereddevice?
Great tutorials by the way.
In the case you indicate, the compiler will error out because Copier isn't allowed to call the constructor of PoweredDevice directly if it's not virtual.
These are good tutorials
Very good article ! Thanks a ton !
EXCELLENT TUTORIAL........... THANKS ALOT MR.ALEX....
Please explain me the solution of diamond problem in terms of vtable & vptr .
thanks bady.....
Hi friends,
Explanation given is only helpful for basic user and for Desktop application.
But in Embedded u require more information. for example how Compiler store this information that only 1 object will be initiated.
like for virtual function we have virtual table concept
The most derived class. How it is so misleading. One would've assumed it's the class which is most derived from (which is, in this case, the base class). They should've named it deriving class, so that at least Alex's tutorial would be easier to understand :)
HI ALEX,
WOULD YOU PLEASE EXPLAIN TO ME WHY MOST DERIVED CLASS IS RESPONSIBLE FOR CREATION OF 'VIRTUAL BASE'?
The short answer is: a virtual base class is always considered a direct base of its most derived class. Thus, even though it appears like PoweredDevice is a base class of Scanner and Printer, it's actually a base of Copier, and the compiler does some interesting tricks to make Scanner and Printer work as expected.
I'm not sure why this rule was picked (instead of making construction of the virtual base class the responsibility of the class doing this "joining").
please can you explain other problems about inheritance?
Great!! Excellent explanation. Last 3 points are very good, something i have not known earlier.
Hi this is very good one
Hi,
how i will solve dimond problem in multiple inheritence with out using "VIRTUAL" keyword.
please help me out...
HI venkatesh,
You can use scope resolution operator for diamond problem with multiple inheritance.
This is great article. I should have read this before going to interviews :)
Thanks for the tutorial. I understood everything but this part not:
"First, virtual base classes are created before non-virtual base classes, which ensures all bases get created before their derived classes."
Why virtual bases are created before non-virtual bases?
Regards.
Simply put, creating the virtual base classes first ensures all virtual base classes get created before the non-virtual classes that may need them.
In this case, it doesn't really matter since neither Scanner nor Printer use anything from PoweredDevice. But if they did, you'd definitely want to ensure PoweredDevice had been initialized before Scanner or Printer.
this is good explanation.Could you please tell me about an extra pointer is created when we do virtual inheritance.If i want to know size of copier class what it will be and how?
The extra pointer comes about because the compiler has to set up a virtual table to make the classes that inherit from the virtual base work correctly. We talk about the virtual table in chapter 12.
You explained that very well, Alex. Wasn't hard to understand at all.
Hi Alex,
I have read somewhere like "base class construtor,destructor,assignment operator and copy constuctors will not get inherited to derived class". Why is it so? Can u explain me?
sandhya, constructor and destructor can not be inherited because a constructor have same name as its class and i don't think there are two classes existing in your program having same name....
this is also true in case of destructor