1

Similar, but not identical to, THIS QUESTION:

    A
  /   \
 B     C
  \   /
    D

What I want is:

struct A { virtual void func (void) = 0; };

struct B : virtual A { void func (void) {} };
struct C : virtual A { void func (void) {} };

struct D : B,C { void func (void) {} };

int main ()
{
    A *p = new D();
    ((C*) p)->func(); // do C::func
    ((B*) p)->func(); // do B::func
}

According to THIS QUESTION this does not seem to be a problem so long the inheritance is just multiple inheritance and not a diamond. why does this not work with a diamond shape?

Apparently its ambiguous, but what I want to be able to do is cast the pointer and hence use a different parent implementation of the virtual function, i.e.:

((C*) p)->func(); //does C::func

If I run the code above I run into the error:

error: cannot convert from pointer to base class 'A' to pointer to derived class 'C' because the base is virtual
 ((C*)p)->func();

which I tried to google but cannot find anywhere

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • *"why does this not work with a diamond shape"* - your definition of "work", what you expect this code would do, and what it actually does, are all significant to this question, and should be [included in your post](https://stackoverflow.com/posts/52244794/edit). – WhozCraig Sep 09 '18 at 13:09
  • nothing in that answer question explains how something like `((C*) p)->func();` would be possible or why it isnt – user10230251 Sep 09 '18 at 13:15
  • Reopened. Neither of the purported duplicates addresses the question asked here. This question isn't about how to use virtual inheritance; it's about converting from a base pointer to a derived pointer. – Pete Becker Sep 09 '18 at 13:19
  • 1
    If you want direct parent implementation then you need to specify the to-be-called implementation directly. Otherwise the virtual member wins. The syntax notwithstanding, [see it live here](https://ideone.com/kirY23). – WhozCraig Sep 09 '18 at 13:20
  • thank you that is exactly what i wanted `p->C::func()` strange syntax, very interesting, much appreciated – user10230251 Sep 09 '18 at 13:25

1 Answers1

1

Since func is virtual throughout the hierarchy, any direct call to func through a pointer to any of the types involved will call D::func. To do the cast in the code in the question, use dynamic_cast<C*>(p). But that doesn't remove the virtual-ness of func, so that will end up calling D::func, just as p->func() does.

To get rid of the virtual-ness, you have to name the class as well as the function. In a simpler context:

D *d = new D;
d->C::func(); // calls C::func

When you have a pointer to the base type instead of a pointer to the derived type you have to convert the pointer to a type that has C::func. That conversion is done with dynamic_cast, like this:

A *p = new D;
dynamic_cast<C*>(p)->C::func();

Depending on your compiler, you might have to fiddle with your class definitions a bit to get rid of linker errors. Some compilers get confused with inheritance from classes with no non--inline functions.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165