这是一个关于指针的概要static_cast<>
,dynamic_cast<>
特别是它们与指针有关的内容。这只是一个101级的纲要,并没有涵盖所有的错综复杂。
static_cast< 类型* >(ptr)
这会将指针放入ptr
并尝试将其安全地转换为 type 的指针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 的指针Type*
。但是这个转换是在运行时执行的,而不是编译时。因为这是一个运行时强制转换,所以在与多态类结合使用时尤其有用。事实上,在某些情况下,类必须是多态的,才能使强制转换合法。
强制转换可以沿两个方向之一进行:从基础到派生 (B2D) 或从派生到基础 (D2B)。看看 D2B 转换如何在运行时工作很简单。要么ptr
来自,要么Type
不是。对于 D2B dynamic_cast<>s,规则很简单。您可以尝试将任何内容转换为其他任何内容,如果ptr
实际上是从 派生的Type
,您Type*
将从dynamic_cast
. 否则,您将得到一个 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;
的强制转换绝对不是类型安全的。你怎么能解决这个问题?一种方法是AreYouABar() const = 0;
在基类中添加一个类似 bool 的函数,并true
从Bar
和false
from中返回Foo
。但是还有另一种方法:使用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;
}