Search

11.8 — Virtual base classes

Note: This section is an advanced topic and can be skipped or skimmed if desired.

In the previous section on multiple inheritance, we left off talking about the “diamond problem”. In this section, we will resume this discussion.

Virtual base classes

Here is our example from the previous lesson, with some constructors:

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:

This produces the result:

PoweredDevice: 3
Scanner: 1
PoweredDevice: 3
Printer: 2

As you can see, PoweredDevice got constructed twice.

While this is sometimes what you want, other times you may want only one copy of PoweredDevice to be shared by both Scanner and Printer. 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 that is shared. Here is the an example (without constructors for simplicity) showing how to use to virtual keyword to create a shared base class:

Now, when you create a Copier class, you will get only one copy of PoweredDevice 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:

This time, our previous example:

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 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. If we are 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, the virtual keyword is ignored, 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.

12.1 -- Pointers and references to the base class of derived objects
Index
11.7 -- Multiple inheritance

33 comments to 11.8 — Virtual base classes

  • prABU

    i was not satisfied with ur explian, i need more definitions for vitual base classes

  • sandhya

    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?

    • saini

  • Stuart

    You explained that very well, Alex. Wasn’t hard to understand at all.

  • sonika

    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?

  • Stefan

    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.

  • gazelle

    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.

    I think this is somewhat contradicting.can you elaborate it more..

    Thanks in advance..

  • This is great article. I should have read this before going to interviews πŸ™‚

  • venkatesh

    Hi,

    how i will solve dimond problem in multiple inheritence with out using “VIRTUAL” keyword.
    please help me out…

  • RAVI

    Hi this is very good one

  • addy

    Great!! Excellent explanation. Last 3 points are very good, something i have not known earlier.

  • obba

    please can you explain other problems about inheritance?

  • saini

  • A. Syukri Abdollah

    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 πŸ™‚

  • Salve Sayali

    “Copier is still responsible for creating PoweredDevice.”???

  • Lokesh

    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

  • deepak.sisodiya

    thanks bady…..

  • bantoo011

    Please explain me the solution of diamond problem in terms of vtable & vptr .

  • omer3547

    hac? Γ§ok ii anlatmi?sin eline sa?l?k

  • EXCELLENT TUTORIAL……….. THANKS ALOT MR.ALEX….

  • Jeanne

    Very good article ! Thanks a ton !

  • Leo

    These are good tutorials

  • sandeep

    int main()
    {
    int *pnPtr = new int;
    delete pnPtr;
    *pnPtr = 4;
    cout<<*pnPtr;
    }

    please explain me why the output of this code is 4?

    • David

      When you call

      You are deleting whatever value is in the memory address the pointer is pointing to. However, the pointer is still pointing to that memory address. The difference here is that the pointer is pointing to a (now) empty memory address. When you call

      you are assigning the value ‘4’ to the memory address the pointer is pointing to.

    • Ben

      It’s actually not always 4. The output of that code may be 4, some other number, or a nasty crash, depending on what else is happening on your computer at the same time.

      David’s answer is very intuitive and well put, but not quite correct. (After all, nothing in C++ is intuitive or well put. If you think something makes sense, that’s probably a red flag. πŸ™‚ )

      When you call

      , you’re *technically* not deleting an int. You *would* be deleting an int, except that an int has no destructor. Your code says, allocate heap space for an int, make an int there (that is to say, do nothing, since you didn’t supply a value), destroy the int (that is to say, do nothing again, since ints don’t have destructors), and then deallocate its memory. So you’re just getting some memory that was available at the time you got it, doing nothing with it, and giving it back.

      The reason your code will *usually* output 4 is because you use your pointer *immediately* after deallocating it, so it’s unlikely to have since become unavailable.

      Just because you *can* use memory that no longer belongs to you doesn’t mean it’s a good idea. Particularly, this is because sometimes you can get away with it, and sometimes you can’t, and there’s no trivial way to tell whether you can or not at any given moment. Messing with memory that doesn’t belong to your program is just asking for trouble.

  • Frank

    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.

    • Alex

      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.

  • Octavian

    "multiple inheritance" link at the top of the page points to this page. It should point to previous section being 11.7.

  • Ryan B

    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)?

  • Ryan B

    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)?

    • Alex

      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.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter

  

  

  

twelve + nineteen =