Virtual inheritance...

Discussion in 'C++' started by JKop, Nov 3, 2004.

  1. JKop

    JKop Guest

    I'm starting to think that whenever you derive one class from another, that
    you should use virtual inheritance *all* the time, unless you have an
    explicit reason not to. I'm even thinking that there shouldn't have been a
    "virtual" keyword for this purpose, but instead, a "nonvirtual" keyword!


    In teaching inheritance, you see the common example:


    class Vehicle {}

    class Car : public Vehicle {}

    class Boat : public Vehicle {}


    But in my opinion, this *most basic* example should be:


    class Vehicle {}

    class Car : virtual public Vehicle {}

    class Boat : virtual public Vehicle {}


    I'm thinking that one should stick in virtual inheritance *everywhere*,
    unless there's an explicit reason not to. Here's one reason why:


    class Vehicle {}

    class Car : virtual public Vehicle {}

    class Boat : virtual public Vehicle {}

    class CarBoat : virtual public Car, virtual public Boat {}


    Here we can see that it's preferrable to use virtual inheritance
    *everywhere* unless you've an explicit reason not to.


    Even going further:


    class Vehicle {}

    class Vehicle_Land : virtual public Vehicle {}
    class Vehicle_Water : virtual public Vehicle {}
    class Vehicle_Air : virtual public Vehicle {}
    class Vehicle_Space : virtual public Vehicle {}

    class Car : virtual public Vehicle_Land {}

    class Motorcycle : virtual public Vehicle_Land {}

    class Boat : virtual public Vehicle_Water {}

    class Plane : virtual public Vehicle_Air {}

    class Helicopter : virtual public Vehicle_Air {}

    class SpaceShuttle : virtual public Vehicle_Space {}


    class CarBoat : virtual public Car, virtual public Boat {}

    class HelicopterMotorcycle : virtual public Helicopter, virtual public
    Motorcycle{}

    class UltimateVehicle : virtual public HelicopterMotorcycle, virtual public
    SpaceShuttle {}


    Now... "UltimateVehicle" looks like so:


    -----------
    | Vehicle |
    -----------
    ^ ^ ^
    ___________| | |______________
    / | \
    / | \
    | | |
    | | |
    ---------------- --------------- -----------------
    | Vehicle_Land | | Vehicle_Air | | Vehicle_Space |
    ---------------- --------------- -----------------
    ^ ^ ^
    | | |
    | | |
    -------------- -------------- ----------------
    | Motorcycle | | Helicopter | | SpaceShuttle |
    -------------- -------------- ----------------
    ^ ^ ^
    | | |
    \ / /
    \ / /
    \ / /
    \ / /
    \ / /
    ------------------------ /
    | MotorcycleHelicopter | /
    ------------------------ /
    ^ /
    | /
    \ /
    \ /
    \ /
    \ /
    \ /
    -------------------
    | UltimateVehicle |
    -------------------



    And this is exactly what we want. We've not explicit reason to make *any* of
    the inheritances non-virtual.

    Any thoughts on this?


    One more thing, why is it called "virtual" inheritanc? I see no similarity
    whatsoever between *it* and the "virtual" keyword applied to a function.


    -JKop
    JKop, Nov 3, 2004
    #1
    1. Advertising

  2. "JKop" <> wrote in message
    news:aU2id.40747$...
    > I'm starting to think that whenever you derive one class from another,
    > that
    > you should use virtual inheritance *all* the time, unless you have an
    > explicit reason not to. I'm even thinking that there shouldn't have been a
    > "virtual" keyword for this purpose, but instead, a "nonvirtual" keyword!


    Let's look at the drawbacks of using virtual inheritance
    - various overheads in object size and performance will be incurred:
    slower access to base class members and slower casts (including
    implicit ones), and one pointer added to instances for each
    base class.
    - downcasting will not be possible with static_cast,
    but require calls to dynamic_cast
    - all subclasses will have to explicitly initialize each
    parent class (except where default initialization is required).
    The last issue might be the most annoying in terms of code
    maintenance, and loss of encapsulation in general.

    When using virtual inheritance, a class doesn't control
    the initialization of its base classes anymore. This
    is an unacceptable drawback in many cases.

    ....
    > In teaching inheritance, you see the common example:

    ....
    > I'm thinking that one should stick in virtual inheritance *everywhere*,
    > unless there's an explicit reason not to. Here's one reason why:


    In teaching inheritance, most authors and instructors say
    that multiple inheritance is to be avoided.

    In practice, few are the object oriented frameworks that
    actually use multiple inheritance (MI) in ways that require
    virtual inheritance. Many languages don't even support MI.

    Even when using MI, the intent is not always to share
    a single instance of the common base classes.

    > class Vehicle {}
    >
    > class Car : virtual public Vehicle {}
    >
    > class Boat : virtual public Vehicle {}
    >
    > class CarBoat : virtual public Car, virtual public Boat {}
    >
    >
    > Here we can see that it's preferrable to use virtual inheritance
    > *everywhere* unless you've an explicit reason not to.


    This is the canonical example where virtual inheritance
    is needed. But really, it is not such a common occurences.
    Most of the uses of MI I've seen in commercial frameworks
    don't need virtual inheritance.

    > Even going further:
    >
    > class Vehicle {}
    > class Vehicle_Land : virtual public Vehicle {}
    > class Vehicle_Water : virtual public Vehicle {}
    > class Vehicle_Air : virtual public Vehicle {}
    > class Vehicle_Space : virtual public Vehicle {}
    > class Car : virtual public Vehicle_Land {}
    > class Motorcycle : virtual public Vehicle_Land {}
    > class Boat : virtual public Vehicle_Water {}
    > class Plane : virtual public Vehicle_Air {}
    > class Helicopter : virtual public Vehicle_Air {}
    > class SpaceShuttle : virtual public Vehicle_Space {}
    > class CarBoat : virtual public Car, virtual public Boat {}
    > class HelicopterMotorcycle : virtual public Helicopter, virtual public
    > Motorcycle{}
    > class UltimateVehicle : virtual public HelicopterMotorcycle, virtual
    > public
    > SpaceShuttle {}

    ....
    > And this is exactly what we want. We've not explicit reason to make *any*
    > of
    > the inheritances non-virtual.
    >
    > Any thoughts on this?

    Multiple inheritance here is only relevant for direct
    subclasses of "Vehicle". In other derivations, the virtual
    inheritance may even have undesirable effects in some
    designs. One may want to keep two copies of a common
    base class.

    > One more thing, why is it called "virtual" inheritanc? I see no similarity
    > whatsoever between *it* and the "virtual" keyword applied to a function.


    C++ designers don't like to add new keywords, so there is a tendency
    to overload their meaning. But in both cases, 'virtual' reflects
    the idea of the addition of some overhead which introduces
    a dynamic run-time aspect that will create some overhead ;)


    The key thing is: I do not agree with your points because:
    1) Multiple inheritance (in the OOP paradigm) is best avoided altogether
    2) Virtual inheritance reduces encapsulation, and requires all base
    classes (direct or indirect) to be initialized by each subclass.
    3) Even when MI is needed, virtual inheritance is not always desirable.
    4) Virtual inheritance, just like virtual functions, is associated
    with an overhead which is unnecessary in most cases.


    Cheers,
    Ivan
    --
    http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
    Ivan Vecerina, Nov 3, 2004
    #2
    1. Advertising

  3. JKop

    JKop Guest


    > Let's look at the drawbacks of using virtual inheritance
    > - various overheads in object size and performance will be incurred:
    > slower access to base class members and slower casts (including
    > implicit ones), and one pointer added to instances for each
    > base class.



    Oh I just realized something (I think):


    Just as how an object contains a hidden pointer to a virtual function... as
    in:


    class Blah
    {
    private:

    char* t;

    public:

    int k;

    virtual int Monkey(double k)
    {
    return 87;
    }
    };


    An object of "Blah" might look something like the following in memory:

    ------------------------------------
    | Pointer to the function "Monkey" |
    ------------------------------------
    | t |
    ------------------------------------
    | k |
    ------------------------------------


    Well... similarly, if you have the following:


    class Ape {}

    class Monkey : virtual public Ape { int rent; }


    Might an object of "Monkey" look like the following in memory?:


    -----------------------------
    | Pointer to the Ape object |
    -----------------------------
    | rent |
    -----------------------------


    That would explain why it's called "virtual inheritance". Am I right?


    -JKop
    JKop, Nov 3, 2004
    #3
  4. "JKop" <> wrote in message
    news:J44id.40754$...
    >
    >> Let's look at the drawbacks of using virtual inheritance
    >> - various overheads in object size and performance will be incurred:
    >> slower access to base class members and slower casts (including
    >> implicit ones), and one pointer added to instances for each
    >> base class.

    >
    >
    > Oh I just realized something (I think):
    >
    >
    > Just as how an object contains a hidden pointer to a virtual function...
    > as
    > in:


    Actually, an object with virtual functions will (typically) store
    a hidden pointer to a static *array* of virtual function pointers.
    RTTI information is often stored next to the same table.

    This way the array is shared by all instances of a class,
    and each instance only stores a single pointer for any number
    of virtual functions.

    > Well... similarly, if you have the following:
    >
    >
    > class Ape {}
    >
    > class Monkey : virtual public Ape { int rent; }
    >
    >
    > Might an object of "Monkey" look like the following in memory?:
    >
    >
    > -----------------------------
    > | Pointer to the Ape object |
    > -----------------------------
    > | rent |
    > -----------------------------

    | Instance of "Ape" object | <--- added
    -----------------------------

    Also, the pointer may actually be an offset to the Ape instance.

    > That would explain why it's called "virtual inheritance".
    > Am I right?


    The two are not identical, and other implementations are possible,
    so this similarity does not really justify using the same name.


    hth -Ivan
    --
    http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
    Ivan Vecerina, Nov 3, 2004
    #4
  5. JKop

    DaKoadMunky Guest

    >Here we can see that it's preferrable to use virtual inheritance
    >*everywhere* unless you've an explicit reason not to.


    I can't see that.

    Care to explain why you think it is preferrable?
    DaKoadMunky, Nov 4, 2004
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. maxw_cc
    Replies:
    1
    Views:
    3,137
    Martijn van Steenbergen
    Dec 21, 2003
  2. qazmlp
    Replies:
    19
    Views:
    789
    Daniel T.
    Feb 4, 2004
  3. cppsks
    Replies:
    0
    Views:
    819
    cppsks
    Oct 27, 2004
  4. Ashwin
    Replies:
    2
    Views:
    345
    Pierre Barbier de Reuille
    Aug 1, 2006
  5. Replies:
    1
    Views:
    465
    Alf P. Steinbach
    Mar 14, 2009
Loading...

Share This Page