B* b = new D();
D* d = dynamic_cast<D*>(b);
在上面的例子中,大多数编译器会通过检查 b 的 vtable 指针是否指向派生类 D 的 vtable 来实现动态转换。如果是,它只是返回 b 的地址作为返回值,否则它返回一个 nullptr。这是执行动态演员表时可能在幕后发生的事情:-
class car
{
public:
virtual void drive()
{
std::cout <<"car"<<std::endl;
}
};
class toyota: public car
{
public:
virtual void drive()
{
std::cout <<"toyota"<<std::endl;
}
};
class honda: public car
{
public:
virtual void drive()
{
std::cout <<"honda"<<std::endl;
}
};
template <typename Tderived>
Tderived* dynamicCast(void* pBase)
{
//compare the vptr of the class pointed by pBase with a temporary Tderived class.
//If vptr of pBase and vptr of Tderived() are pointing to the same vtable
//then it can be safely deduced that pBase is indeed pointing to an instance of Tderived
if (*(int**)pBase == *(int**)&Tderived())
{
return (Tderived*)pBase;
}
else
{
return nullptr;
}
}
int main()
{
car* pCar;
honda hondaCar;
toyota toyotaCar;
pCar = &toyotaCar;
honda* pHonda = dynamicCast<honda>(pCar);
if (nullptr != pHonda)
{
pHonda->drive();
}
else
{
toyota* pToyota = dynamicCast<toyota>(pCar);
if (nullptr != pToyota)
{
pToyota->drive();
}
}
}
Now, if the class is not polymorphic, there is no way for the compiler to find whether pCar is pointing to honda or toyota car. Note that this is just one of the ways to implement dynamic_cast as the C++ standard does not talk anything about vtables.