c++ dynamic_cast 和 static_cast 的区别

今天在看王道宝典的时候看到dynamic_cast ,一直都没用过,也不了解,今天来总结一下。

dynamic_cast 和 static_cast 都可以用来强制转换指针类型,但不同的是dynamic_cast在进行类层次间的下行转换时更加安全

dynamic_cast 运算符可以在执行期决定真正的类型。如果下行转换是安全的(也就是说,如果基类指针或者引用确实指向一个派生类对象),这个运算符会传回转型过的指针。如果下行转换不安全,这个运算符会传回空指针(也就是说,基类指针或者引用没有指向一个派生类对象)。

说了这么多是什么意思呢?总结可以是两句话:

1)在类层次间进行上行转换时,dynamic_cast 和 static_cast 的效果是一样的。

2)在类层次间进行下行转换时,dynamic_cast 具有类型检查的功能,比static_cast 更安全。

例子:下述代码中,若调用函数 func 的实参指向一个B类型的对象,语句1和语句2有什么差别?

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class B{
 5 public:
 6     B():b(1){}
 7     virtual void foo(){};
 8     int b;
 9 };
10 
11 class D:public B{
12 public:
13     D():d(2){}
14     int d;
15 };
16 
17 void func(B *pb){
18     D *pd1 = static_cast<D *>(pb);//语句1
19     cout<<pd1->b<<endl;
20     cout<<pd1->d<<endl;
21     
22     D *pd2 = dynamic_cast<D *>(pb);//语句2
23     cout<<pd2->b<<endl;
24     cout<<pd2->d<<endl;
25 }
26 
27 int main(){
28     //B* pb = new D;
29     //func(pb);
30     B* pb = new B;
31     func(pb);
32     return 0;
33 }

一、在上面的代码中,如果pb指向一个D类型的对象,即

    B* pb = new D;
    func(pb);    

输出:

pd1,pd2是一样的,正常得到结果,这两个指针执行D类型的任何操作都是安全的。

二、但是,如果pb指向的是一个B类型的对象,即

   B* pb = new B;
    func(pb);

输出:

那么pd1将是一个指向B对象的指针,对它进行D类型的操作将是不安全的(如访问d),输出d的值时,将会是一个垃圾值(此次输出是0),延后了错误的发现;

而pd2将是一个空指针,对空指针进行操作,将会发生异常,从而能够更早地发现错误。

 此外,还需注意的一点是 使用dynamic_cast 必须要声明virtual字段,即要有虚函数表!错误输出如下:

这是因为dynamic_cast 运行时类型检查需要类型信息,而这个类型信息存储在类的虚函数表中,只有定义了虚函数的类才有虚函数表,所以编译错误。而static_cast 则没有这个限制

以上是dynamic_cast 和 static_cast 的区别

 

posted @ 2018-03-24 18:53  Hwangzhiyoung  阅读(882)  评论(0编辑  收藏  举报