Thread: why do people shy away from multiple inheritance?

  1. #1
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838

    why do people shy away from multiple inheritance?

    personally i think it's a great language feature: amazingly powerful and easy to use.

    why do so many people recoil at the mention of it?

  2. #2
    Registered User
    Join Date
    May 2006
    Posts
    903
    Off the top of my head I could name the infamous diamond problem.

    class a {};

    class b1 : public a {};
    class b2 : public a {};

    class c : public b1, public b2 {}; // oops, boom !

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    What?
    Code:
    class A
    {
    };
    
    class B : virtual public A
    {
    };
    
    class C : virtual public A
    {
    };
    
    class D : public B, public C
    {
    };
    I see no problem. People shy away from multiple concrete class inheritance because it can become very hard to maintain. It is quite common in several design patterns to derive from multiple abstract base classes to define objects.

    Code:
    class InterfaceA
    {
        public:
            virtual ~InterfaceA() { }
            virtual void DoSomethingA() = 0;
    };
    
    class InterfaceB
    {
        public:
            virtual ~InterfaceB() { }
            virtual void DoSomethingB() = 0;
    };
    
    class IObject
    {
        public:
            virtual ~IObject() { }
            virtual void Foo() = 0;
    };
    
    class Object : public IObject, public InterfaceA, public InterfaceB
    {
        public:
            Object() { }
            virtual void DoSomethingA() { }
            virtual void DoSomethingB() { }
            virtual void Foo() { }
    };
    
    class DifferentObject : public IObject, public InterfaceA, public InterfaceB
    {
        public:
            DifferentObject() { }
            virtual void DoSomethingA() { }
            virtual void DoSomethingB() { }
            virtual void Foo() { }
    };
    
    class ObjectContainer
    {
        public:
            ObjectContainer() { }
            IObject * GetObject(size_t index) {return m_Objects[index];}
            void AddObject(IObject * pObject) {m_Objects.push_back(pObject);}
    
        private:
            std::vector<IObject *> m_Objects;
    };
    As you can see this is very powerful since now you can have objects that may implement A and B's behavior differently and because they all derive from IObject they can be stored in a container. This also paves the way for abstract factories and the like.

    But multiple inheritance, concrete or otherwise, is not bad design. GUI's often use multiple concrete inheritance where everything derives from some base with basic window functionality. Most other GUI elements are windows but then they expose behavior specific to the type of control they are.
    Also the STL and stream classes use multiple concrete inheritance and do quite well.
    Last edited by VirtualAce; 02-13-2009 at 07:26 PM.

  4. #4
    Registered User
    Join Date
    May 2006
    Posts
    903
    "If a method in D calls a method defined in A (and does not override the method), and B and C have overridden that method differently, then from which class does it inherit: B, or C?"

    http://en.wikipedia.org/wiki/Diamond_problem

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by m37h0d View Post
    personally i think it's a great language feature: amazingly powerful and easy to use.

    why do so many people recoil at the mention of it?
    Because too often it is done just to gain access to functionality of another class -- the protected keyword encourages this by creating a netherworld where subclasses can plug into functionality they may have no business accessing.

    Multiple inheritance should still follow the rule of "is-a" relationships. If C inherits A and B, then casting a C* to either A* or B* should still produce an object that performs a useful function.

    Java allows multiple inheritance purely through interfaces, requiring the class to implement all functionality itself, which is one step better -- you can simulate interfaces in C++ by creating pure-virtual classes.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    Quote Originally Posted by Desolation View Post
    "If a method in D calls a method defined in A (and does not override the method), and B and C have overridden that method differently, then from which class does it inherit: B, or C?"

    http://en.wikipedia.org/wiki/Diamond_problem
    in that case you it is ambiguous and you HAVE to specify the scope of the method you want.

    why would you expect it to be otherwise?

  7. #7
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Perhaps its just me, but I have never run across a real problem that required multiple inheritance to solve. It's an interestign feature of the language, but it hasn't been particularly useful to me yet.

  8. #8
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    i'm not sure MI is ever required because the functionality of this:

    Code:
    class b
    {
    };
    class d1:b
    {
    };
    class d2:b
    {
    };
    class d3:d1,d2
    {
    };
    can always be accomplished by:

    Code:
    class b
    {
    };
    class d1:b
    {
    };
    class d2:b
    {
    };
    class d3:b
    {
    d1 _d1;
    d2 _d2;
    };
    personally i think MI is cleaner and more efficient.

  9. #9
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Off the top of my head I could name the infamous diamond problem.
    Which is an exaggerated problem thanks to virtual inheritance and/or protected/private inheritance.

    I have never run across a real problem that required multiple inheritance to solve.
    O_o

    Sure, it's a nice language, but have you ever run across a real problem that required C++?

    i'm not sure MI is ever required [...]always be accomplished by[...]
    O_o

    Rubbish.

    Containment isn't inheritance. Inheritance isn't containment.

    If you need an object, maybe an instance of 'd3', that "is-constrainable-as" a 'd1' object and a 'd2' object, containment will do nothing for you.

    Soma

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by phantomotap View Post
    Containment isn't inheritance. Inheritance isn't containment.
    While that's true, any class with multiple base classes can be repackaged as a class that contains instances of the base classes (or, in the case of abstract bases with data members, instances of objects that contain the equivalent data) and a set of member functions that act as forwarders to the contained objects and data.

    Like any language feature, there are trade-offs in using MI versus an alterative. The reason many people recoil from MI isn't because MI is inherently evil. The real reason is that most people don't take the time to fully understand the trade-offs (some of the rules are moderately complex), so they use MI in an inappropriate manner, and get bitten.

    Support of MI in a programming language is somewhat challenging to implement: the semantics are somewhat complex, and getting them right in a compiler takes a lot of work. In the interests of reducing compiler complexity (or complexity of semantics in the language) some programming language designers simply take the easy way out and disallow MI. If forced to defend their choice, the language designer then claims that MI is evil/complex/unnecessary/bug-ridden/unmaintainable/etc and naive programmers simply lap up that message (after all, they've tried to use it and gotten bitten because they didn't understand the trade-offs) and therefore shy away from MI.

  11. #11
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    Quote Originally Posted by phantomotap View Post
    O_o

    Rubbish.

    Containment isn't inheritance. Inheritance isn't containment.

    If you need an object, maybe an instance of 'd3', that "is-constrainable-as" a 'd1' object and a 'd2' object, containment will do nothing for you.

    Soma
    eh - as usual absolutes don't lend themselves well to reality. most functionality of inheritance can be simulated using containment.

    i suppose if d1 and d2 both introduced a virtual method that d3 overrode, then containment does not fit the bill, and one woudl have to resort to using a function pointer, which defeats convenience of virtual methods in the first place. much like containment defeats inheritance.

  12. #12
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    While that's true, any class [...] contained objects and data.
    RUBBISH!

    I don't care how your language spells "multiple inheritance" or how you may restate, this will remain rubbish, trash, garbage, worthless, completely freaking false.

    A class containing instances of other classes isn't necessarily constrainable as the classes it contains regardless of any forwarding functions you wish to create.

    You have only described parametric polymorphism.

    Parametric polymorphism is a fine thing. I'm a huge fan. It isn't multiple inheritance. It does not mimic multiple inheritance. It is not containment. It does not require containment.

    i suppose if [...] defeats inheritance.
    If containment was always an alternative to multiple inheritance then you could override the relevant virtual method by deriving 'd3_d1' from 'd1', 'd3_d2' from 'd2', and containing both 'd3_d1' and 'd3_d2' in 'd3'.

    Containment isn't always an alternative to multiple inheritance in exactly the same way that containment isn't always an alternative to single inheritance... and vice versa.

    Soma

  13. #13
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by phantomotap View Post
    RUBBISH!

    I don't care how your language spells "multiple inheritance" or how you may restate, this will remain rubbish, trash, garbage, worthless, completely freaking false.
    Now that you've thoroughly demonstrated your ignorance of the topic at hand, I guess we can move on.


    Next!!!!
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  14. #14
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    Quote Originally Posted by soma
    If containment was always an alternative to multiple inheritance then you could override the relevant virtual method by deriving 'd3_d1' from 'd1', 'd3_d2' from 'd2', and containing both 'd3_d1' and 'd3_d2' in 'd3'.

    Containment isn't always an alternative to multiple inheritance in exactly the same way that containment isn't always an alternative to single inheritance... and vice versa.

    Soma
    can an equivalent structure always be created using containment and single inheritance? probably not. i am sure that you (yes even YOU!) would be hard pressed to conceive many such situations where it cannot be done with those two techniques with enough elaboration.

  15. #15
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Why does it seem to be everyone's goal to remove inheritance in favor of always using a different approach? Why is it that we consistently have to have it 100% one way or 100% another way? It is my estimation that if the language provides approved constructs and your use of the construct is in line with its design then you are just using the right tool for the job. No one ever throws away a screwdriver because it isn't a good hammer.

    I personally feel those that relegate themselves to this or that but not both are not very useful practical programmers. Get the job done and use the right tool or right construct for the job. What is the big deal? I will readily admit that I use multiple inheritance when the problem warrants it and aggregation when the situation warrants it. I could care less about books and other so called 'better' languages that don't offer multiple inheritance. C++ offers it, supports it, and is not removing it. Therefore, when appropriate, I will utilize it to get my projects completed. If other languages don't offer multiple inheritance, like C#, then I will find another way to solve the problem. But just because C# and Java and Billy and Bob and Moe don't offer multiple inheritance does not mean it's wrong to use it in C++. So lighten up and go program something.
    Last edited by VirtualAce; 02-14-2009 at 12:00 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Exception handling framework based on multiple inheritance
    By Mario F. in forum C++ Programming
    Replies: 11
    Last Post: 06-25-2007, 10:17 AM
  2. Katrina Aftermath: Woeful Incompetence (rant).
    By anonytmouse in forum A Brief History of Cprogramming.com
    Replies: 61
    Last Post: 09-05-2005, 07:39 AM
  3. God
    By datainjector in forum A Brief History of Cprogramming.com
    Replies: 746
    Last Post: 12-22-2002, 12:01 PM
  4. C++ multiple inheritance problem
    By pongsor in forum C++ Programming
    Replies: 7
    Last Post: 02-08-2002, 08:18 PM
  5. Multiple virtual inheritance
    By kitten in forum C++ Programming
    Replies: 3
    Last Post: 08-10-2001, 10:04 PM