Upcasting to a C++ class that is a base class in more than one way (without having to use virtual inheritance)

Viewed 320
class A { };
class B : public  A {};
class C : public A, public B {};

int main()
{
    C c;
    A *pA = static_cast<A *>(&c);
}

In the above code, class C is derived from class A in two different paths: 1. Directly from A 2. Indirectly through B i.e. A<-B<-C

So, when I cast an object of class C into a pointer to class A, g++ on Linux reports the following error: error: A is an ambiguous base of C

I have also tried the same code by removing the static cast as follows: A *pA = &c; But, I still get exactly the same error.

Is there any solution for this? BTW, the same works fine without error on Windows using Visual C++ compiler.

I know that virtual inheritance solves this but I need a solution to make this work on g++ on Linux without having to use virtual inheritance. Rather than having to use virtual inheritance, is there any way I can instead specify one of the two path and get rid of the ambiguity. Many thanks!

2 Answers

If you can modify C, one possible approach would be to "inject" a dummy base class between it and A:

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

int main()
{
    C c;
    A *pA = static_cast<A*>(static_cast<AlmostA*>(&c));
}

[Live example]

You can even embed the dual static casts into a function in C.

Long story short, inherit from A virtually to avoid having two distinct As being a part of C:

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

Now your code will compile and run correctly.

Unlike "regular" base classes, virtual base classes are inherited only once, regardless of the number of paths that have them. Read this Q&A for a detailed explanation of how they work.

Related