二、dynamic_cast
dynamic_cast 仅允许把 指针类型或引用类型 转换成 对象,从而获得一个完整的对象。通常的应用场景是,把派生类的指针转换成基类的指针。
看以下程序dynamic_cast.cpp:
1 int main(){ 2 CBase b; CBase* pb; 3 CDerived d; CDerived* pd; 4 pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base 5 pd = dynamic_cast<CDerived*>(&b); // wrong: base-to-derived 6 7 int dwA=10, *pB = NULL; 8 short int *pA=NULL, wB =20; 9 pA = dynamic_cast<short int *> (&dwA); // wrong: 10 pB = dynamic_cast<int *> (&wB); // wrong: 11 }
第5行编译错误的原因是:cannot dynamic_cast '& b' (of type 'class CBase*') to type 'class CDerived*' (source type is not polymorphic). 基类指针不能通过dynamic_cast 转换成派生类指针。
第9行编译错误的原因是:cannot dynamic_cast '& dwA' (of type 'int*') to type 'short int*' (target is not pointer or reference to class) dynamic_cast操作符的target和source都必须是指向某对象的指针或引用,而不能是指向基本数据结构的指针。
第10行和第9行的原因一样。
在使用多态特性时,dynamic_cast操作符因为在编译器无法判断类型转换是否“合理”,不会在编译期提示错误。 但是当遇到基类指针通过dynamic_cast转化成派生类指针时(如dynamic_cast_polymorphic.cpp的第15行),会返回空指针。
1 // dynamic_cast_polymorphic.cpp 2 #include <iostream> 3 #include <exception> 4 using namespace std; 5 6 class CBase { virtual void dummy() {} }; 7 class CDerived: public CBase { int a; }; 8 9 int main () { 10 try { 11 CBase * pb1 = new CDerived; 12 CBase * pb2 = new CBase; 13 CDerived * pd1, *pd2; 14 pd1 = dynamic_cast<CDerived*>(pb1);// derived -> derived 15 pd2 = dynamic_cast<CDerived*>(pb2);// base -> derived, pd2 is null pointer. 16 cout<<endl; 17 } 18 catch (exception& e) {cout << "Exception: " << e.what();} 19 return 0; 20 }
通过gdb可以看到各指针所指向的实际地址。
(gdb) print pb1
$1 = (CBase *) 0x502010
(gdb) print pb2
$2 = (CBase *) 0x502030
(gdb) print pd1
$3 = (CDerived *) 0x502010
(gdb) print pd2
$4 = (CDerived *) 0x0 // 空指针
参考:
http://www.cplusplus.com/doc/tutorial/typecasting/