When is dynamic_cast the ONLY way that works?


If we know the cast is safe, we can use static_cast for downcasting in almost all cases.
Have a look at this example:

struct CMultiBase1
{
	int mbase1;
	virtual void f() {	};
};
struct CMultiBase2
{
	int mbase2;
	virtual void f() {	};
};
struct CMultiSub: CMultiBase1, CMultiBase2
{
};
void TestMulti()
{
	CMultiSub s;
	CMultiSub *pFrom1Static, *pFrom1Dynamic, *pFrom2Static, *pFrom2Dynamic;
	CMultiBase2 *p2 = &s;
	CMultiBase1 *p1 = &s;
	pFrom1Static = static_cast<CMultiSub *>(p1);
	pFrom1Dynamic = dynamic_cast<CMultiSub *>(p1);
	pFrom2Static = static_cast<CMultiSub *>(p2);
	pFrom2Dynamic = dynamic_cast<CMultiSub *>(p2);
	_ASSERT(pFrom1Static == pFrom1Dynamic && pFrom2Static == pFrom2Dynamic
		&& pFrom1Static == &s && pFrom2Static == &s);
}

No matter how we downward cast them, we always get &s, and therefore static_cast can be used for dynamic_cast.
However, in the following snippet, dynamic_cast is the only way that works:

struct CMultiBase
{
	int mbase;
	virtual void f() {	};
};
struct CMultiBase1: virtual CMultiBase
{
	int mbase1;
};
void TestVirtualSingleInheritance()
{
	CMultiBase1 b1;
	b1.mbase1 = 2;
	CMultiBase *pb = &b1;
	CMultiBase1 *pb1 = dynamic_cast<CMultiBase1 *>(pb); //no other cast works here
	_ASSERT(pb1->mbase1 == 2); //dynamic_cast is good
	_ASSERT(reinterpret_cast<void**>(pb1) + 2 == reinterpret_cast<void*>(pb));
	//pb1 = static_cast<CMultiBase1 *>(pb); //compiling error
	pb1 = reinterpret_cast<CMultiBase1 *>(pb);
	_ASSERT(pb1->mbase1 != 2); //reinterpret_cast casts to the wrong pointer
}

It’s impossible to cast from virtual base pointer to derived pointer without RTTI. dynamic_cast is the only one that can use RTTI. Therefore, dynamic_cast is the only way here.

Advertisements

2 Comments

  1. QbProg

     /  December 29, 2011

    Nice one 🙂 I didn’t know it!

    BTW, may I suggest to use more understandable name,
    CMultiBase and CMultiBase1 are easily confused when reading the code.
    What about “Base” and “Derived” or “VirtualDerived”
    Or “A”, “B” 🙂
    Same for the locals!

  2. Rio Wing

     /  December 29, 2011

    Thanks for the suggestions, which for sure I’ll follow. Blogging is a process of learning.

%d bloggers like this: