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();
}
}
}
ここで、クラスがポリモーフィックでない場合、pCar がホンダ車またはトヨタ車のどちらを指しているかをコンパイラーが検出する方法はありません。C++ 標準は vtables について何も述べていないため、これは dynamic_cast を実装する方法の 1 つにすぎないことに注意してください。