今天在看王道宝典的时候看到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 的区别