Multiple Inheritance Diamond: Why ambiguous conversion?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct Base
{
        virtual ~Base() = 0;
};
struct Sub1 : public Base
{
        virtual ~Sub1() = 0;
};
struct Sub2 : public Base
{
        virtual ~Sub2() = 0;
};
struct Implementor : public Sub1, public Sub2
{
        virtual ~Implementor(){}
};
 
int main()
{
        Base *p;
        p = new Implementor(); //ambiguous conversion? how?
        delete p;
}

I can't really see what makes the implicit conversion ambiguous; could someone explain this concept to me? Having to cast to one of either Sub1 or Sub2 at my discretion seems odd.

EDIT: I've read that it has to do with the 'more direct path' - which makes no sense to me because of the way virtual member functions don't path down the inheritance tree and instead simply jump right to the correct function. You would think it would be consistent for implicit pointer conversion...
Last edited on
In this case, Implementor actually contains (is?) two instances of Base: the Base obtained by casting up through Sub1 and the Base obtained by casting up through Sub2.

Doing this:

p = static_cast<Sub1*>( new Implementor() );

or this:

p = static_cast<Sub2*>( new Implementor() );

will make the error go away.

If you want Implementor to be one Base instance, then virtual inheritance* is in order.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct Base
{
        virtual ~Base() {}; //this example won't compile with these being pure virtual
};
struct Sub1 : public virtual Base
{
        virtual ~Sub1() {};
};
struct Sub2 : public virtual Base
{
        virtual ~Sub2() {};
};
struct Implementor : public Sub1, public Sub2
{
        virtual ~Implementor(){}
};
 
int main()
{
        Base *p;
        p = new Implementor();
        delete p;
}


*http://en.wikipedia.org/wiki/Virtual_inheritance
Last edited on
Huh, I never even knew about that virtual inheritance. Every time I ask a question here I learn something new and mindset changing, and I am happy for that.

Now I have an new problem. I have the default constructor, copy constructor, and assignment operators all private and undefined in all involved classes, because they only have one public constructor that takes a certain parameter. I now have to call the constructor of the base class from ALL of the classes it seems, not just the ones that directly inherit it. Is this correct?

EDIT: Also, I did have my destructors implemented - I just wanted a simple example that showed that the first three classes were abstract. (some compilers can't handle virtual ~SomeClass() = 0 {})
Last edited on
Yes, because with virtual inheritance (going with your exmaple), Base becomes a direct base class of Implementor.
Thanks for all your help - I have it working properly now and it is actually less buggy than before (I guess because the dual base thing was causing issues).
Last edited on
Topic archived. No new replies allowed.