Alex Rivera | Logout

C++ - downcasting a diamond shape inherited object without RTTI/dynamic_cast

Asked 2010-07-27T20:52:54.067
15

I'm currently working on integrating a third-party package that uses lots of RTTI stuff on a non-RTTI platform (Android). Basically, I did my own RTTI implementation but I'm stuck on a problem.

The issue is that a lot of classes are having the diamond inheritance problem since all the classes derive from the same base class (object).. and so, if I want to downcast from the base class to the derived class, I have to use a dynamic_cast - but RTTI is not available! How do I convert an object from parent to child when there are virtual inheritance without dynamic_cast?

It looks like that:

class A 
{
public:
 virtual char* func() { return "A"; };
};
class B : public virtual A
{
public:
 //virtual char* func() { return "B"; };
};
class C : public virtual A 
{
public:
 //virtual char* func() { return "C"; };
};

class D : public B, public C 
{
public:
 //virtual char* func() { return "D"; };
};

D d;
A* pa = static_cast<A*>(&d);
D* pd = static_cast<D*>(pa); // can't do that! dynamic_cast does work though...

Those are my errors:

error C2635: cannot convert a 'A*' to a 'D*'; conversion from a virtual base class is implied

error C2440: 'initializing' : cannot convert from 'test_convert::A *' to 'test_convert::D *' Cast from base to derived requires dynamic_cast or static_cast

Any ideas?

Edit
Report

1 Answer

1

the code:

template <typename E, typename T>
E& force_exact(const T& ref)
 {
   static const E* exact_obj;
   static const T& exact_obj_ref = *exact_obj;
   static const ptrdiff_t exact_offset = ...

doesn't work very well for me as static const E* exact_obj is zero, so static const T& exact_obj_ref = *exact_obj derefs zero, too, and thus static const ptrdiff_t exact_offset becomes also zero.

It seems to me that the derived class needs to be instantiated (which may be a problem for abstract classes...). So my code is:

template <typename D, typename B>
D & Cast2Derived(B & b)
{ static D d;
  static D * pD = & d;
  static B * pB = pD;
  static ptrdiff_t off = (char *) pB - (char *) pD;

  return * (D *) ((char *) & b - off);
} 

Tested under MSVC 2008, WinXP 32b.

Any comments / better solution(s) are welcome.

LuP

answered 2011-08-19T09:37:59.623

Your Answer