ambiguity in diamond inheritance

Discussion in 'C++' started by karthikbalaguru, Mar 6, 2008.

  1. Hi,

    I wonder why is there an ambiguity in diamond
    inheritance when we try to call the method in the
    parent class from the class derived from multiple
    (two)childs of the parent class.
    Why C++ does not handle it internally and give us the
    path to access the method in the parent class ?
    Any constraints ?

    Thx in advans,
    Karthik Balaguru
    karthikbalaguru, Mar 6, 2008
    #1
    1. Advertising

  2. karthikbalaguru

    Guest

    On 6 Mar, 11:38, karthikbalaguru <> wrote:
    >
    > I wonder why is there an ambiguity in diamond
    > inheritance when we try to call the method in the
    > parent class from the class derived from multiple
    > (two)childs of the parent class.
    > Why C++ does not handle it internally and give us the
    > path to access the method in the parent class ?
    > Any constraints ?


    See
    http://www.parashift.com/c -faq-lite/multiple-inheritance.html#faq-25.9
    , Mar 6, 2008
    #2
    1. Advertising

  3. karthikbalaguru

    dizzy Guest

    karthikbalaguru wrote:

    > Hi,
    >
    > I wonder why is there an ambiguity in diamond
    > inheritance when we try to call the method in the
    > parent class from the class derived from multiple
    > (two)childs of the parent class.
    > Why C++ does not handle it internally and give us the
    > path to access the method in the parent class ?
    > Any constraints ?


    1. there are no C++ methods, there are only member functions of various
    types, let's supose you mean normal (non static, non virtual) member
    function

    2. if it were to be able to call it, on what instance of the common base it
    should do it? Because if you have a diamond, you got 2 instances of the
    common base, one though one branch of the diamond and the other through the
    other so it should call the member function on which of these instances?
    Thus the ambiguity

    If instead, you wanted to have a single common base even if it's inherited
    (indirectly) multiple times then you should look over "virtual inheritance"
    in your C++ book.

    --
    Dizzy
    dizzy, Mar 6, 2008
    #3
  4. karthikbalaguru

    Guest

    On Mar 6, 3:38 am, karthikbalaguru <>
    wrote:
    > Hi,
    >
    > I wonder why is there an ambiguity in diamond
    > inheritance when we try to call the method in the
    > parent class from the class derived from multiple
    > (two)childs of the parent class.
    > Why C++ does not handle it internally and give us the
    > path to access the method in the parent class ?
    > Any constraints ?
    >
    > Thx in advans,
    > Karthik Balaguru


    Let's say we have four classes: A, B, C, and D
    B & C both derive from A
    D derives from B & C

    D essentially "contains" two A sub-objects. One for the B part and
    one for the C part. Consider the following code:

    #include <iostream>

    class A
    {
    int n;
    public:
    A(int i) : n(i) {};
    virtual void f() { std::cout << "From A: " << n << std::endl; }
    };

    class B : public A
    {
    public:
    B() : A(30) {};
    };

    class C : public A
    {
    public:
    C() : A(50) {};
    };

    class D : public B, public C {};

    int main()
    {
    D d;
    d.C::f(); //prints 50
    d.B::f(); //prints 30
    return 0;
    }

    If both B & C had derived virtually from A:
    class B : public virtual A {/*...*/};
    class C : public virtual A {/*...*/};
    Then D would only have one A sub-object. In this case, D would be
    responsible for constructing A.
    , Mar 7, 2008
    #4
  5. On Mar 6, 6:19 pm, dizzy <> wrote:
    > karthikbalaguru wrote:
    > > Hi,

    >
    > > I wonder why is there an ambiguity in diamond
    > > inheritance when we try to call the method in the
    > > parent class from the class derived from multiple
    > > (two)childs of the parent class.
    > > Why C++ does not handle it internally and give us the
    > > path to access the method in the parent class ?
    > > Any constraints ?

    >
    > 1. there are no C++ methods, there are only member functions of various
    > types, let's supose you mean normal (non static, non virtual) member
    > function
    >
    > 2. if it were to be able to call it, on what instance of the common base it
    > should do it? Because if you have a diamond, you got 2 instances of the
    > common base, one though one branch of the diamond and the other through the
    > other so it should call the member function on which of these instances?
    > Thus the ambiguity


    I understand the Diamond Problem and the solution of "Virtual
    Inheritance"
    that is used to overcome ambiguity.
    But, i wonder why should the Diamond problem arise. This should
    be taken care by C++ internally and resolved. Why C++ could not
    handle it internally without asking us to do the 'virtual
    inheritance'?

    Thx in advans,
    Karthik Balaguru
    karthikbalaguru, Mar 7, 2008
    #5
  6. > I understand the Diamond Problem and the solution of "Virtual
    > Inheritance"
    > that is used to overcome ambiguity.
    > But, i wonder why should the Diamond problem arise. This should
    > be taken care by C++ internally and resolved. Why C++ could not
    > handle it internally without asking us to do the 'virtual
    > inheritance'?



    If c++ would automatically resolve the ambiguity, then how would you
    be able to have 2 separate instances ?

    Base Base
    | |
    | |
    | |
    Der1 Der2
    \ /
    \ /
    \ /
    Join


    I know it would be a bad design to have such a structure, but just in
    case someone wanted to have a non-diamond structure.... c++ allows
    it.
    Shobhit Gupta, Mar 7, 2008
    #6
  7. karthikbalaguru

    Pete Becker Guest

    On 2008-03-06 23:34:45 -0500, karthikbalaguru
    <> said:

    >
    > I understand the Diamond Problem and the solution of "Virtual
    > Inheritance"
    > that is used to overcome ambiguity.
    > But, i wonder why should the Diamond problem arise. This should
    > be taken care by C++ internally and resolved. Why C++ could not
    > handle it internally without asking us to do the 'virtual
    > inheritance'?
    >


    "The Diamond Problem" arises because the writer of a class hierarchy
    didn't understand how inheritance works.

    struct A
    {
    int i;
    };

    struct B : A
    {
    };

    struct C : A
    {
    };

    struct D : B, C
    {
    void f();
    };

    void D::f()
    {
    i = 3; // error: ambiguous
    }

    There are two separate "i" members in D. There's no way the compiler
    can "handle it internally". You have to say what you mean:

    void D::f()
    {
    B::i = 3; // OK: B's "i" member
    }

    If you don't want to have two "I" members in D, then the inheritance
    hierarchy as written above is wrong. If the design calls for only one A
    subobject, you do that by making A a virtual base everywhere. Then
    there's only one "i" member in D. But note that that's a design
    decision, not an implementation decision. Either you have only one A
    subobject, in which case "i" is unambibuous, or you have two, and you
    have to say which one you mean.

    --
    Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
    Standard C++ Library Extensions: a Tutorial and Reference
    (www.petebecker.com/tr1book)
    Pete Becker, Mar 7, 2008
    #7
  8. karthikbalaguru

    Pete Becker Guest

    On 2008-03-07 08:07:37 -0500, Shobhit Gupta <> said:

    >
    > If c++ would automatically resolve the ambiguity, then how would you
    > be able to have 2 separate instances ?
    >
    > Base Base
    > | |
    > | |
    > | |
    > Der1 Der2
    > \ /
    > \ /
    > \ /
    > Join
    >
    >
    > I know it would be a bad design to have such a structure, but just in
    > case someone wanted to have a non-diamond structure.... c++ allows
    > it.


    It's not a bad design if it's the correct solution to the problem. For
    example, if Base is a node that can for a linked list, Join can be an
    element in two lists.

    --
    Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
    Standard C++ Library Extensions: a Tutorial and Reference
    (www.petebecker.com/tr1book)
    Pete Becker, Mar 7, 2008
    #8
  9. > It's not a bad design if it's the correct solution to the problem. For
    > example, if Base is a node that can for a linked list, Join can be an
    > element in two lists.



    That sounds right. I was thinking of other scenarios, like having BASE
    class contain some information. (In that case its better to use
    composition.)
    But thats something very true, if anything is a correct solution, its
    probably the right design for the user.
    Shobhit Gupta, Mar 7, 2008
    #9
  10. karthikbalaguru

    Guest

    On Mar 6, 8:34 pm, karthikbalaguru <>
    wrote:

    > I understand the Diamond Problem and the solution of "Virtual
    > Inheritance"
    > that is used to overcome ambiguity.
    > But, i wonder why should the Diamond problem arise. This should
    > be taken care by C++ internally and resolved. Why C++ could not
    > handle it internally without asking us to do the 'virtual
    > inheritance'?
    >
    > Thx in advans,
    > Karthik Balaguru


    Read my example above and consider this:
    d.C::f() prints out 50
    d.B::f() prints out 30
    What should d.f() print out?

    Should the compiler just guess which one you meant? Or are you asking
    why non-virtual inheritance is the default?
    , Mar 7, 2008
    #10
  11. On Mar 8, 2:16 am, wrote:
    > On Mar 6, 8:34 pm, karthikbalaguru <>
    > wrote:
    >
    > > I understand the Diamond Problem and the solution of "Virtual
    > > Inheritance"
    > > that is used to overcome ambiguity.
    > > But, i wonder why should the Diamond problem arise. This should
    > > be taken care by C++ internally and resolved. Why C++ could not
    > > handle it internally without asking us to do the 'virtual
    > > inheritance'?

    >
    > > Thx in advans,
    > > Karthik Balaguru

    >
    > Read my example above and consider this:
    > d.C::f() prints out 50
    > d.B::f() prints out 30
    > What should d.f() print out?
    >
    > Should the compiler just guess which one you meant?  Or are you asking
    > why non-virtual inheritance is the default?


    Yes, i am asking why non-virtual inheritance is the default.

    Thx in advans,
    Karthik Balaguru
    karthikbalaguru, Mar 8, 2008
    #11
  12. On Mar 8, 6:23 am, karthikbalaguru <>
    wrote:
    > On Mar 8, 2:16 am, wrote:
    >
    >
    >
    >
    >
    > > On Mar 6, 8:34 pm, karthikbalaguru <>
    > > wrote:

    >
    > > > I understand the Diamond Problem and the solution of "Virtual
    > > > Inheritance"
    > > > that is used to overcome ambiguity.
    > > > But, i wonder why should the Diamond problem arise. This should
    > > > be taken care by C++ internally and resolved. Why C++ could not
    > > > handle it internally without asking us to do the 'virtual
    > > > inheritance'?

    >
    > > > Thx in advans,
    > > > Karthik Balaguru

    >
    > > Read my example above and consider this:
    > > d.C::f() prints out 50
    > > d.B::f() prints out 30
    > > What should d.f() print out?

    >
    > > Should the compiler just guess which one you meant?  Or are you asking
    > > why non-virtual inheritance is the default?

    >
    > Yes, i am asking why non-virtual inheritance is the default.
    >

    Apologies.
    Yes, i am asking the first one - 'Should the compiler just guess
    which one you meant ?' and not the second part of your post.

    Thx in advans,
    Karthik Balaguru
    karthikbalaguru, Mar 8, 2008
    #12
  13. On Mar 7, 6:11 pm, Pete Becker <> wrote:
    > On 2008-03-06 23:34:45 -0500, karthikbalaguru
    > <> said:
    >
    >
    >
    > > I understand the Diamond Problem and the solution of "Virtual
    > > Inheritance"
    > > that is used to overcome ambiguity.
    > > But, i wonder why should the Diamond problem arise. This should
    > > be taken care by C++ internally and resolved. Why C++ could not
    > > handle it internally without asking us to do the 'virtual
    > > inheritance'?

    >
    > "The Diamond Problem" arises because the writer of a class hierarchy
    > didn't understand how inheritance works.
    >
    > struct A
    > {
    > int i;
    >
    > };
    >
    > struct B : A
    > {
    >
    > };
    >
    > struct C : A
    > {
    >
    > };
    >
    > struct D : B, C
    > {
    > void f();
    >
    > };
    >
    > void D::f()
    >     {
    >     i = 3;      // error: ambiguous
    >     }
    >
    > There are two separate "i" members in D. There's no way the compiler
    > can "handle it internally".


    But, Why is the compiler unable to handle it internally ?

    > You have to say what you mean:
    >
    > void D::f()
    >     {
    >     B::i = 3;   // OK: B's "i" member
    >     }
    >
    > If you don't want to have two "I" members in D, then the inheritance
    > hierarchy as written above is wrong. If the design calls for only one A
    > subobject, you do that by making A a virtual base everywhere. Then
    > there's only one "i" member in D. But note that that's a design
    > decision, not an implementation decision. Either you have only one A
    > subobject, in which case "i" is unambibuous, or you have two, and you
    > have to say which one you mean.
    >
    > --
    >   Pete
    > Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
    > Standard C++ Library Extensions: a Tutorial and Reference
    > (www.petebecker.com/tr1book)
    karthikbalaguru, Mar 8, 2008
    #13
  14. karthikbalaguru

    James Kanze Guest

    On 8 mar, 08:57, karthikbalaguru <> wrote:
    > On Mar 7, 6:11 pm, Pete Becker <> wrote:
    > > On 2008-03-06 23:34:45 -0500, karthikbalaguru
    > > <> said:


    > > > I understand the Diamond Problem and the solution of
    > > > "Virtual Inheritance" that is used to overcome ambiguity.
    > > > But, i wonder why should the Diamond problem arise. This
    > > > should be taken care by C++ internally and resolved. Why
    > > > C++ could not handle it internally without asking us to do
    > > > the 'virtual inheritance'?


    > > "The Diamond Problem" arises because the writer of a class
    > > hierarchy didn't understand how inheritance works.


    > > struct A
    > > {
    > > int i;
    > > };


    > > struct B : A
    > > {
    > > };


    > > struct C : A
    > > {
    > > };


    > > struct D : B, C
    > > {
    > > void f();
    > > };


    > > void D::f()
    > > {
    > > i = 3; // error: ambiguous
    > > }


    > > There are two separate "i" members in D. There's no way the
    > > compiler can "handle it internally".


    > But, Why is the compiler unable to handle it internally ?


    Handle what? How is the compiler supposed to know which i
    (B::A::i or C::A::i) you want to refer to?

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Mar 8, 2008
    #14
  15. karthikbalaguru

    James Kanze Guest

    On 8 mar, 02:23, karthikbalaguru <> wrote:
    > On Mar 8, 2:16 am, wrote:
    > > On Mar 6, 8:34 pm, karthikbalaguru <>
    > > wrote:
    > > > I understand the Diamond Problem and the solution of
    > > > "Virtual Inheritance" that is used to overcome ambiguity.
    > > > But, i wonder why should the Diamond problem arise. This
    > > > should be taken care by C++ internally and resolved. Why
    > > > C++ could not handle it internally without asking us to do
    > > > the 'virtual inheritance'?


    > > Read my example above and consider this:
    > > d.C::f() prints out 50
    > > d.B::f() prints out 30
    > > What should d.f() print out?


    > > Should the compiler just guess which one you meant? Or are
    > > you asking why non-virtual inheritance is the default?


    > Yes, i am asking why non-virtual inheritance is the default.


    Mainly history, I suspect. Non-virtual inheritance has some
    performance impacts, and is rarely needed at the application
    level (and when it is needed there, it's easy to determine
    where, and explicitly declare it). It's true, however, that far
    too many frameworks use non-virtual inheritance where virtual
    would be required: when in doubt, inheritance should be virtual
    (which argues for virtual inheritance being the default).

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Mar 8, 2008
    #15
    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. Alexander Stippler

    virtual inheritance / dreaded diamond problem

    Alexander Stippler, Jul 14, 2003, in forum: C++
    Replies:
    0
    Views:
    1,876
    Alexander Stippler
    Jul 14, 2003
  2. Alexander Stippler

    virtual inheritance / dreaded diamond again

    Alexander Stippler, Aug 26, 2003, in forum: C++
    Replies:
    1
    Views:
    388
    Ron Natalie
    Aug 26, 2003
  3. Tom
    Replies:
    3
    Views:
    500
  4. John Perks and Sarah Mount

    MRO problems with diamond inheritance?

    John Perks and Sarah Mount, May 1, 2005, in forum: Python
    Replies:
    13
    Views:
    599
    Michele Simionato
    May 3, 2005
  5. Alex Hunsley
    Replies:
    4
    Views:
    366
    Colin J. Williams
    Nov 2, 2005
Loading...

Share This Page