在C++中,dynamic_cast和static_cast都是用来转型的操作符,两者不合理的运用可能会导致在编译期合法的类型转换操作却在运行期也会引发错误,当转型操作涉及到对象指针或引用时,更易发生错误。 这两者又有什么区别呢?
1、dynamic_cast操作符会在运行期对可疑的转型操作进行安全检查,而static_cast操作符不会进行安全检查;
2、dynamic_cast仅对多态有效(转型的源类型必须是多态,但与转型的目标类型是否多态无关),而static_cast可施加与任何类型;
3、从派生类到基类的 dynamic_cast 可以进行,这称为向上转型;
4、从基类到派生类的 dynamic_cast 不能进行,称为向下转型;
5、有继承关系,派生类可通过dynamic_cast向基类转换;
6、没有继承关系,不能通过dynamic_cast互换;
使用方式:
dynamic_cast<T*>ptr、static_cast<T*>ptr;
dynamic_cast<T&>p、static_cast<T*>p;
下面用一些简单的代码来说明关于转型的一些知识点:
一个基类指针不经过明确的转型操作,就能指向基类对象或派生类对象;反过来,一个派生类指针指向基类对象是一种不明智的做法。
1 class B 2 { 3 ... 4 }; 5 class D : public B 6 { 7 ... 8 }; 9 int main( ) 10 { 11 D* p; 12 p = new B(); // error 13 p = static_cast<D*>(new B()); // 合法,但可能会造成难以跟踪的运行错误 14 }
再看下面一段代码:
1 class B 2 { 3 public: 4 virtual void f() { cout<< "f()" <<endl; } 5 }; 6 class D : public B 7 { 8 public: 9 void m(){cout<< "m()" <<endl;} 10 }; 11 int main() 12 { 13 D* p = static_cast<D*>(new B); 14 p -> m(); // ... 15 return 0; 16 }
其中p->m()编译能通过,但运行出错。因为P实际指向一个B的对象,而B没有成员函数m,这种转型不安全(在VS2010中,可正确运行,输出:m())。
C++提供的dynamic_cast操作符可以在运行期检测某个转型动作是否安全。dynamic_cast和static_cast有同样的语法,不过dynamic_cast仅对多态类型有效。
1 class C 2 { 3 // C类中无虚函数 4 }; 5 class T 6 { 7 }; 8 int main( ) 9 { 10 T* p = dynamic_cast<T*>(new C()); // error,仅对多态类型有效 11 return 0; 12 }
注意:dynamic_cast操作正确的前提是——转型的源类型必须是多态的, 但与转型的目标类型是否多态无关。 在<>中指定的dynamic_cast的目的类型必须是一个指针或引用。
看一个正确的用法:
1 class B 2 { 3 public: 4 virtual void f() {cout << "f()" << endl;} 5 }; 6 class D:public B 7 { 8 public: 9 void m() {cout << "m()" << endl;} 10 }; 11 int main() 12 { 13 D* p = dynamic_cast<D*>(new B()); // 能够判断转型是否安全,如果安全,则返回B对象的地址,否则返回NULL。本例返回NULL。 14 if (p) 15 { 16 p -> m(); 17 } 18 else 19 { 20 cout << “Error\n"; 21 } 22 return 0; 23 }
若有不对或不全的欢迎指正和补充——