4
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!

psk
  • 41
  • 2
  • 1
    First, your inheritance tree is a code smell. Second, what you are looking for is virtual inheritance. Look that up ;) – YSC Sep 22 '17 at 14:30
  • Can you please elaborate on why you need two separate inherited instances of `A` in your `C`? Is composition an option? – Mark B Sep 22 '17 at 15:21
  • 1
    @YSC -- no, changing the **design** is not a solution to a **coding** problem. It's not unreasonable to have **two** bases of the same type, and it's not unreasonable to ask how to manage them. – Pete Becker Sep 22 '17 at 15:47
  • 1
    Re: "I know that virtual inheritance solves this" -- not really. If you need two instances of the base class, changing to virtual inheritance eliminates the **coding** problem but also eliminates the two bases that were part of the original design. – Pete Becker Sep 22 '17 at 15:48
  • @PeteBecker who suggested a change in design? I surely did not! – YSC Sep 22 '17 at 16:49
  • 1
    @YSC - "what you are looking for is virtual inheritance" suggests a design change, going from **two** copies of `A` to **one** copy of `A`. – Pete Becker Sep 22 '17 at 16:57
  • @PeteBecker Ho that, yes you're right. Read a bit too quick. – YSC Sep 22 '17 at 17:04

2 Answers2

4

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.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
0

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.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    I had assumed the OP actually needed two separate `A` instances due to the way the question was formulated. – Mark B Sep 22 '17 at 14:35
  • @MarkB Given that there are no members in any of OP's classes, it is hard to tell if his intention was to have one or two `A`s in a `C`. To me it is highly unusual to want to have two `A`s, so I made an assumption that OP wants a single one. – Sergey Kalinichenko Sep 22 '17 at 14:38