0

Consider following simple example:

#include <iostream>
using namespace std;

class A {
public:
    virtual void foo() {
        cout<<"A"<<endl;
    }
};

class B: public virtual A {
public:
    virtual void foo(){
        cout<<"B"<<endl;
    }
};

class C : public virtual A {
public:
    virtual void foo(){
        cout<<"C"<<endl;
    }
};

class D : public B, public C {
    public:
        void print(){
            foo();
        }
};

int main () {
    D d;
    d.print();
    return 0;
}

This code will not work, because call to foo is ambigous. But question is:

How can I define which methods from which classes should be inherited? And if I have the such opportunity?

  • 4
    Basically there's one question and one advice: Q: What's your specific use-case for multiple inheritance ambiguity to occur? A: Don't use multiple inheritance, since there's almost always a way around, leading to more explicit designs. – MABVT Aug 23 '15 at 09:25
  • @MABVT Multiple inheritance is extremely useful and alternatives usually add complexity. – curiousguy Aug 23 '15 at 10:40
  • @curiousguy Hm. Multiple inheritance itself might be useful, if you don't have to deal with those ambiguity concerns! In fact i rarely had use cases for Mult.Inh. with conscious ambiguity being involved before... Oo Just being curious: Do you have any specific examples, where OPs situation occurrs and is in fact in a useful context? Seems like i can learn something new at this point. ;) – MABVT Aug 23 '15 at 10:45
  • @MABVT Do you often get ambiguities with MI? When you do, it is a difficult problem? – curiousguy Aug 23 '15 at 11:01
  • It is certainly a dup, but the dupped question mentioned is different. – curiousguy Aug 23 '15 at 11:02
  • @curiousguy Since i hardly use MI, I don't encounter problems. A classic example I found in a book years ago for that situation was: class Vehicle { virtual void move(); }; class Car : public Vehicle { virtual void move(); }; class Boat : public Vehicle { virtual void move(); }; class AmphibianVehicle : public Car, public Boat { void move(); }; This way I had to distinguish using Car::move();... Since I became a OOP guy due to work I'd rather declare interfaces and use another approach. – MABVT Aug 23 '15 at 11:07
  • @MABVT Since `Vehicle` is an interface, you should derive virtually. – curiousguy Aug 23 '15 at 11:18
  • @curiousguy In this case Vehicle is a standalone class not meant to be an interface. The example above is not using any interface (in OOP sense )at all. – MABVT Aug 23 '15 at 11:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/87694/discussion-between-curiousguy-and-mabvt). – curiousguy Aug 23 '15 at 11:33
  • 2
    @MABVT No one says, that MI is panacea or it is better than some other solutions. I like answer on question "Does MI needed?" from this FAQ. I recommend you to read this section of FAQ https://isocpp.org/wiki/faq/multiple-inheritance – Roman Tymchyshyn Aug 23 '15 at 14:21
  • @RomanTymchyshyn Thanks for the link. Very useful indeed. – MABVT Aug 23 '15 at 14:52

1 Answers1

1

Disambiguate the call to the function. Take the following example:

class A { virtual void foo(); };
class B { virtual void foo(); };
class C : public A ,public B { void foo(); };

To call either foo from A, B or even from the child class: C do

C *obj = new C;
obj->foo();
obj->A::foo();
obj->B::foo();

Source/inspiration: http://www.cprogramming.com/tutorial/multiple_inheritance.html

Propolys
  • 364
  • 1
  • 16
  • So, you suggest me often write function foo in C-class, where make calls to that variant of foo, which I need? – Roman Tymchyshyn Aug 23 '15 at 10:03
  • Yes, you need to override foo() in class C, but it doesn't necessarily need to do anything. Its use is to make an explicit qualification. Tldr, C::foo() can be empty. – Propolys Aug 23 '15 at 10:06
  • If it can be empty, why even call this function? – curiousguy Aug 23 '15 at 10:41
  • You do not need to call it. It's there just to disambiguate. It can call functions too but not needed. – Propolys Aug 23 '15 at 11:00
  • What is the specification of `foo()`? If the specification allows an empty body, why do you even need this function? – curiousguy Aug 23 '15 at 11:19
  • Just to make everything clear, in my example, the C::foo() is not needed. But in OP's case (diamond inheritance), if you do not declare C::foo(), you will get an ambiguous inheritance error on compilation (most likely). Try it out yourself. – Propolys Aug 23 '15 at 11:40
  • I was only interested in next: are there some constructions in language (not workarounds) which allow to choose variant of inherited method. Thanks for extremly simple and clear answer. – Roman Tymchyshyn Aug 23 '15 at 14:24