4

I'm using C++. When I try to convert a derived class' pointer to base class', compiler complains "base class is ambiguous".

I did some research, and found this question How can I avoid the Diamond of Death when using multiple inheritance?. And some other similar issue.

There is a solution, is to use virtual inheritance. But I'm not able to change class definitions, because they are compiled libraries.

Is that possible to do the converting, without changing base class definitions?

A minimal sample would be:

class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};

What I want to do is:

D *d = new D;
A *a = (D *)d;  // ambiguous
Community
  • 1
  • 1
zhm
  • 3,513
  • 3
  • 34
  • 55
  • How did you end up with such a design? Diamond inheritance is frowned upon for this very reason. – StoryTeller - Unslander Monica Nov 09 '16 at 06:22
  • 1
    The problem is a conceptual one. You don't just "convert pointers" in some opaque, magical way. What you're really doing is obtaining the address of a base subobject from a more derived object. Once you realize that, and the fact that you may have multiple base subobjects of the same type, the solution becomes clear. – Kerrek SB Nov 09 '16 at 06:27
  • I'm maintaining an ancient project, makes it impossible to modify base classes. – zhm Nov 09 '16 at 06:37
  • It would be better if you'd provide a minimal code that illustrated a problem – borisbn Nov 09 '16 at 06:38

2 Answers2

7

Is that possible to do the converting, without changing base class definitions?

Yes it is. You have to choose which direct base class to go through.

class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};

void foo(A&) {}

int main() {
    D d;

    foo(static_cast<B&>(d));
    foo(static_cast<C&>(d));

    return 0;
}
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
3

I found a way to do this converting, a little tricky though.

Following code would do the job:

A *a = (B *)d;
zhm
  • 3,513
  • 3
  • 34
  • 55
  • "(B *)d" can you explain it? I know " * B " what does it mean , but this is confusing – imtithal Jun 07 '20 at 21:31
  • @imtithal This is to explicitly convert `d` to pointer of `B` first. Then compiler will implicitly convert pointer of `B` to pointer of `A` (not ambiguous anymore since `B` has only one parent class). – zhm Jun 29 '20 at 02:26