dynamic_cast和static_cast的差别

    添加时间:2013-6-11 点击量:

      在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 }


      如有不合错误或不全的迎接斧正和补充——

    容易发怒的意思就是: 别人做了蠢事, 然后我们代替他们, 表现出笨蛋的样子。—— 蔡康永
    分享到: