这里是 static_cast<> 和 dynamic_cast<> 的概要,特别是它们与指针有关。这只是一个101级的纲要,并没有涵盖所有的复杂性。
static_cast(ptr)
这将获取ptr 中的指针并尝试将其安全地转换为Type* 类型的指针。这个转换是在编译时完成的。只有当类型相关时,它才会执行强制转换。如果类型不相关,您将收到编译器错误。例如:
class B {};
class D : public B {};
class X {};
int main()
{
D* d = new D;
B* b = static_cast<B*>(d); // this works
X* x = static_cast<X*>(d); // ERROR - Won't compile
return 0;
}
dynamic_cast(ptr)
这再次尝试获取ptr 中的指针并将其安全地转换为Type* 类型的指针。但是这个转换是在运行时执行的,而不是编译时。因为这是一个运行时强制转换,所以在与多态类结合使用时尤其有用。事实上,在某些情况下,类必须是多态的,才能使强制转换合法。
强制转换可以沿两个方向之一进行:从基础到派生 (B2D) 或从派生到基础 (D2B)。看看 D2B 转换如何在运行时工作很简单。 ptr 是从 Type 派生的,或者不是。对于 D2B dynamic_casts,规则很简单。您可以尝试将任何内容转换为其他任何内容,如果ptr 实际上是从Type 派生的,您将从dynamic_cast 得到一个Type* 指针。否则,你会得到一个 NULL 指针。
但 B2D 演员阵容稍微复杂一些。考虑以下代码:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0; // pure virtual
virtual ~Base() {};
};
class Foo : public Base
{
public:
virtual void DoIt() { cout << "Foo"; };
void FooIt() { cout << "Fooing It..."; }
};
class Bar : public Base
{
public :
virtual void DoIt() { cout << "Bar"; }
void BarIt() { cout << "baring It..."; }
};
Base* CreateRandom()
{
if( (rand()%2) == 0 )
return new Foo;
else
return new Bar;
}
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = (Bar*)base;
bar->BarIt();
}
return 0;
}
main() 无法判断CreateRandom() 将返回什么样的对象,因此C 风格的转换Bar* bar = (Bar*)base; 显然不是类型安全的。你怎么能解决这个问题?一种方法是将类似 bool AreYouABar() const = 0; 的函数添加到基类,并从 Bar 返回 true,从 Foo 返回 false。但是还有另一种方式:使用dynamic_cast<>:
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = dynamic_cast<Bar*>(base);
Foo* foo = dynamic_cast<Foo*>(base);
if( bar )
bar->BarIt();
if( foo )
foo->FooIt();
}
return 0;
}
强制转换在运行时执行,并通过查询对象来工作(现在无需担心如何),询问它是否是我们正在寻找的类型。如果是,dynamic_cast<Type*> 返回一个指针;否则返回 NULL。
为了使用dynamic_cast<> 进行这种从基到派生的转换,Base、Foo 和 Bar 必须是标准所称的多态类型。为了成为多态类型,您的类必须至少有一个virtual 函数。如果您的类不是多态类型,dynamic_cast 的基到派生使用将无法编译。示例:
class Base {};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile
return 0;
}
向 base 添加一个虚函数,例如 virtual dtor,将使 Base 和 Der 都成为多态类型:
class Base
{
public:
virtual ~Base(){};
};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // OK
return 0;
}