Inherit from two polymorphic classes

Given the following code

class T { public: virtual ~T () {} virtual void foo () = 0; }; class U { public: U() {} ~U() {} void bar () { std::cout << "bar" << std::endl; } }; class A : public U, public T { public: void foo () { std::cout << "foo" << std::endl; } }; int main () { A * a = new A; std::vector<U*> u; std::vector<T*> t; u.push_back(a); t.push_back(reinterpret_cast<T*>(u[0])); u[0]->bar (); t[0]->foo (); delete a; return 0; } 

I get the output that I would expect

 bar foo 

However, if I changed the definition of U to

 class U { public: U() {} virtual ~U() {} virtual void bar () { std::cout << "bar" << std::endl; } }; 

I still compile everything without warnings / errors, but now the result

 bar bar 

What is a virtual declaration that prevents me from calling foo ?

+2
c ++ multiple-inheritance virtual-functions
source share
3 answers

First, in your example, there are no virtual base classes. Classes containing virtual functions are called polymorphic. (In C ++, there is such a thing as “virtual base classes,” but this has nothing to do with your example.)

Secondly, the behavior of your code does not depend on any virtual declarations. You intentionally destroyed the integrity of the base pointer using reinterpret_cast . For this reason, the behavior of the code is undefined.

Direct conversion from one base pointer to another (what you are trying to do in your code) is called cross-conversion. The only C ++ listing that can perform cross-listing is dynamic_cast .

 t.push_back(dynamic_cast<T *>(u[0])); 

You can do an indirect translation without dynamic_cast , but for this you need to first compress the pointer to the derived type ( A * ) using static_cast , and then convert it to another type of base pointer

 t.push_back(static_cast<A *>(u[0])); // upconversion to `T *` is implicit 
+4
source share

If you use reinterpret_cast , you lose all warranties, and all you do is “undefined behavior”. In this case, I expect VMT to be messed up or overwritten by VPTR.

As an illustration, when I compile the first code above, I get segfault to execute in my compiler.

If you really want to perform cross-execution, you should get a common base class and inherit this base class in U and T practically ( : virtual public ) or use dynamic_cast instead of reinterpret_cast .

+1
source share

Pour t just like you did u :

 t.push_back(a); 

You do not need reinterpret_cast , because A - t .

0
source share

All Articles