在c++中提供了如下方式的类型转换:
dynamic_cast
reinterpret_cast
static_cast
const_cast
dynamic_cast只处理指针和对象的引用。其目的是确保类型转换的结果是一个有效的完整的对象。
因此,dynamic_cast总是能成功地一个类转换到它的一个基类。
class CBase { };
class CDerived: public CBase { };
CBase b; CBase* pb;
CDerived d; CDerived* pd;
pb = dynamic_cast(&d); // ok: derived-to-base
pd = dynamic_cast(&b); // wrong: base-to-derived
第二个转换是错误的,除非基类是多态(polymorphic)。
当一个类是多态,dynamic_cast在运行时会执行一个特殊检查,以确保表达式产生了一个有效的完整的对象:
// dynamic_cast
#include
#include
using namespace std;
class CBase { virtual void dummy() {} };
class CDerived: public CBase { int a; };
int main () {
try {
CBase * pba = new CDerived;
CBase * pbb = new CBase;
CDerived * pd;
pd = dynamic_cast(pba);
if (pd==0) cout << "Null pointer on first type-cast" << endl;
pd = dynamic_cast(pbb);
if (pd==0) cout << "Null pointer on second type-cast" << endl;
} catch (exception& e) {cout << "Exception: " << e.what();}
return 0;
}
尽管两者都是指针的类型CBase *,pba指向一个CDerived类型的对象,而从CDerived指向一个CBase类型的对象。因此,当他们各自的类型铸件执行使用dynamic_cast,pba指向一个完整的CDerived类对象的类,而pbb指向一个不完整的CDerived类的对象。
兼容性注意:dynamic_cast需要运行时类型信息(RTTI)跟踪动态类型。一些编译器支持这个特性作为一个选项,默认情况下是禁用的。这必须启用运行时类型检查使用dynamic_cast正常工作。.
dynamic_cast也可以转换空指针甚至不相关的类之间的指针,也可以把任何类型的指针转换到空指针(void *)。
reinterpret_cast可以完成从任何指针类型到任何其他指针类型的转换,甚至是不相关的类。
由reinterpret_cast但不是static_cast的转换在c++是低级操作,其解释结果通常是系统相关的,因此不可移植的。
class A {};
class B {};
A * a = new A;
B * b = reinterpret_cast(a);
虽然b指向了一个不完整的对象,但是上面的语句是合法的,只不过,当b解引用可能时会产生运行时错误。
static_cast可以执行相关类指针之间的转换,可以从派生类到基类,也可以从基类到派生类。这将确保至少类是兼容的,如果适当的对象被转换,但是在运行时没有执行安全检查,以检查是否被转换的对象实际上是一个完整的对象类型的目的地。
因此,程序员,以确保转换是安全的。但另一方面,dynamic_cast避免的类型安全检查的开销。
class CBase {};
class CDerived: public CBase {};
CBase * a = new CBase;
CDerived * b = static_cast(a);
虽然b指向了一个不完整的对象,但是上面的语句是合法的,只不过,当b解引用可能时会产生运行时错误。
此外,static_cast还可以完成基本类型之间的转换。但是不能转换const, volatile, __unaligned等属性。
const_cast维护对象的常量属性,可以设置或者去掉对象的常量属性:
// const_cast
#include
using namespace std;
void print (char * str)
{
cout << str << endl;
}
int main () {
const char * c = "sample text";
print ( const_cast (c) );
return 0;
}
typeid可以检查变量的类型,并用name()加以输出:
// typeid, polymorphic class
#include
#include
#include
using namespace std;
class CBase { virtual void f(){} };
class CDerived : public CBase {};
int main () {
try {
CBase* a = new CBase;
CBase* b = new CDerived;
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
cout << "*a is: " << typeid(*a).name() << '\n';
cout << "*b is: " << typeid(*b).name() << '\n';
} catch (exception& e) { cout << "Exception: " << e.what() << endl; }
return 0;
}
[1] http://www.cplusplus.com/doc/tutorial/typecasting/
[2] http://msdn.microsoft.com/en-us/library/c36yw7x9%28v=vs.80%29.aspx