Why can't I dynamic_cast sideways during multiple inheritance?

The following code calls std :: bad_cast

struct Foo { void foo () {} }; struct Bar { Bar () { dynamic_cast <Foo &> (*this) .foo (); } virtual ~ Bar () {} }; struct Baz : public Foo, public Bar { }; int main () { Baz b; } 

I remember once reading how dynamic_cast has a trade-off in implementation performance because "it goes through the full inheritance lattice" in order to correctly evaluate it. What the compiler needs to do here will start first and then down again.

Is it possible to do the above work or do I need to add virtual Foo* Bar::as_foo()=0;

+2
source share
4 answers

There are no virtual functions in Foo, so dynamic_cast is bound to fail. There must be a virtual function. It is also a bad idea to do this during construction, as you are going to run into construction problems.

+7
source

Assuming that Bar should inherit from Foo (which is not the case in the current example), the problem you see here is usually called a diamond . Which version of Foo do you want to use, Bar::foo() or Foo::foo() ? You will need to specify virtual inheritance:

 struct Foo{ ~virtual Foo(){} void foo(){} }; struct Bar : virtual public Foo struct Baz : virtual public Foo, public Bar 

so that he knows that there is only one type of foo() . Therefore, virtual inheritance is used to call foo() inside the constructor.

Edit:

And to be clear, I assume that you want Bar inherit from Foo . If you do not have this in the code, then this is the reason for the bad error. There is no inheritance hierarchy for Bar to go to Foo . In addition, modern compilers should not even compile without virtual inheritance, but some legacy compilers would gladly be @ # $ # $ it.

And if I'm going to comment on another answer, I'd rather follow my own answer!

+2
source

There are several errors in your example, maybe this is an accident?

A bar is not inherited from Foo, so it cannot be dropped to Foo in the Bar constructor. They also do not have a common parent of inheritance and therefore cannot be thrown among themselves (sideways). You probably want:

 struct withFoo { virtual void foo () {} virtual ~withFoo() {} }; struct Foo : public virtual withFoo { }; struct Bar : public virtual withFoo { Bar () { foo(); // no need to cast! } }; struct Baz : public Foo, public Bar { }; int main () { Baz b; b.foo(); // because of virtual inheritance from withFoo, there is no ambiguity here } 

Hope this helps! If you need clarification, please ask!

+1
source

Building a Base involves building its foundations, and one of them is the Bar. Base Base Base does not lend itself to Foo, even if the last Baz should be.

0
source

All Articles