Thread: Virtual inheritance

  1. #1
    Registered User
    Join Date
    Nov 2006
    Posts
    184

    Virtual inheritance

    I know that if you're going to inherit from multiple classes that both have the same base, it's much "cleaner" to have them virtually inherit from the base. My question is, what does the "virtual" keyword do and why not just put it on every inheritance to allow later possible multiple inheritance (assuming that fits your model)?

    In other words, if I have a class "A" that inherits from "B" and "C" which both inherit from "D" and I know that "A" might (but also might not) be included in some other class' multiple inheritance (say class "F" that inherits from "A" and "G" both) is it OK to do:

    Code:
    class A : public virtual B, public virtual C
    {
    };
    Does that make any difference performance/memory wise?

  2. #2
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    if i understand you correctly, what you're describing is called diamond inheritance. and it sounds like you're on the right track.


    i can't comment on the performance implications.

    be aware though that the order of the constructor calls can be different under virtual inheritance, which has caused some initialization issues for me.

  3. #3
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    Quote Originally Posted by m37h0d View Post
    if i understand you correctly, what you're describing is called diamond inheritance. and it sounds like you're on the right track.


    i can't comment on the performance implications.

    be aware though that the order of the constructor calls can be different under virtual inheritance, which has caused some initialization issues for me.
    Thanks. I think I'm ok as I've set them up so that they have no-arg constructors that are only called in multiple inheritance cases which should account for that (but I'll double check to be sure)

  4. #4
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    that sounds like what i had to do.

    i still don't have the intialization worked out though myself.

    this sometimes has problems with multiple initialization so i bring this up in hopes someone will disabuse me of my folly, but what i did was to create an init(...) function for each class.

    the first line of any class' init function is to call the immediate ancestor's init function. thus the intialization occurs in the proper order from base to derived.

    however, in the case of multiple inheritance, common ancestors are initialized multiple times, which can lead to leaks :\

    so far, my only thought on how to avoid this is to call a function pointer to init, and have the last line of init set this pointer to NULL.

    i'd much appreciate any suggestions on better strategies.

  5. #5
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by 6tr6tr View Post
    it's much "cleaner" to have them virtually inherit from the base.
    No. It's either correct or incorrect. It's not a manner of cleanness.

    My question is, what does the "virtual" keyword do
    All virtual bases of the same type in an inheritance hierarchy are collapsed into a single one, whereas all non-virtual bases are separate objects.

    and why not just put it on every inheritance to allow later possible multiple inheritance (assuming that fits your model)?
    Because virtual inheritance comes with considerable overhead - speed, size, and complexity.

    In other words, if I have a class "A" that inherits from "B" and "C" which both inherit from "D" and I know that "A" might (but also might not) be included in some other class' multiple inheritance (say class "F" that inherits from "A" and "G" both) is it OK to do:

    Code:
    class A : public virtual B, public virtual C
    {
    };
    Well, it's OK to do, but not exactly useful, unless G also inherits from B and C.

    Does that make any difference performance/memory wise?
    Yes. Every virtual base costs a per-instance pointer. In addition, by making all bases virtual, you can't inherit the virtual pointer from them, so your class may need its own. That's another pointer. Then there's the indirection overhead of member access, and the stub overhead of virtual calls. And finally, the final overriding class is responsible for calling the constructors of its virtual bases - that's probably the worst part of it. It means that a class that has virtual bases in its hierarchy can't just initialize its direct superclasses. Instead, it has to be aware of all virtual indirect bases and initialize those, too.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  6. #6
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    You might want to see if there's a way to redesign your class hierarchy to remove the need to use virtual base classes, and maybe even remove the multiple inheritance. It would make your life a lot easier.

  7. #7
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    First off, thank you very much for the help!

    Quote Originally Posted by CornedBee View Post
    No. It's either correct or incorrect. It's not a manner of cleanness.
    .
    What I meant by that was instead of using "virtual" to inherit, I believe you could also write the specific name for members to have it work as well. For example:

    someObject::ABaseClass::MainBaseClass::someMethod( );

    That's messy but it is technically within the C++ specs.

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    That's not the point. If you inherit non-virtually, you have multiple copies of the base class. If you inherit virtually, you have one. Depending on the situation, one of the two is the correct behaviour, the other is not.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    *bump*

    anyone mind taking a stab at disabusing me of my ignorance of how to resolve initialization issues?

    i have this sneaking feeling that my difficulties stem from the fact that i'm doing it all wrong.

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Basically, virtual ancestors are always initialized by the class that is actually instantiated. If this class forgets the initialization, the default constructor will be used. If there is none, you'll get an error.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  11. #11
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    so doing it the way i described it is a good strategy?

  12. #12
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    No, it isn't. The whole "avoid multiple initialization" thing has already been implemented by the compiler for constructors, so just use those.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  13. #13
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    in some cases when i step through it with the debugger, it goes through the constructors more than once.

    is this indicative of some problem with my code or is this some idiosyncrasy of the debugger?

  14. #14
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    No idea. Does it really go through the full constructor?
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Virtual Inheritance: Building Menu items
    By csonx_p in forum C++ Programming
    Replies: 12
    Last Post: 01-22-2009, 12:28 PM
  2. Replies: 48
    Last Post: 09-26-2008, 03:45 AM
  3. Virtual function and multiple inheritance
    By George2 in forum C++ Programming
    Replies: 68
    Last Post: 02-13-2008, 01:15 AM
  4. C++ XML Class
    By edwardtisdale in forum C++ Programming
    Replies: 0
    Last Post: 12-10-2001, 11:14 PM
  5. Exporting Object Hierarchies from a DLL
    By andy668 in forum C++ Programming
    Replies: 0
    Last Post: 10-20-2001, 01:26 PM