c++中的 static_cast 和 dynamic_cast
dynamic_cast用于类层次的上行转换(派生类向基类转换)以及下行转换(基类向派生类转换),相比 static_cast ,其安全性要高一点儿。考虑如下的情形:
#include <iostream>
using std::cout;using std::endl;
class base{
public:
base(int val):a(val){}
virtual void print(){
cout << "base's print()\n";
}
public:
int a;
};
class derived:public base{
public:
derived(int val1,int val2):base(val1),b(val2){}
virtual void print(){
cout << "derived's print()\n";
}
public:
int b;
};
int main(){
base *p_base;
derived *p_derived;
base base_obj(1);
derived derived_obj(2,3);
p_base = &base_obj;
p_derived = static_cast<derived*>(p_base);
cout << p_derived->b;
p_derived = dynamic_cast<derived*>(p_base);
if(p_derived != NULL){
std::cout << p_derived->b;
}
}
上面中的cout << p_derived->b
得到的值是一个莫名其妙的值,其原因在于我们的p_derived
虽然是一个derived
指针,但是其指向的却是一个base
对象,p_defrived
的静态类型仅仅决定编译器如何解释p_derived
指向的内存区域,这里我们将指向base
对象base_obj
的指针p_base
通过static_cast
运算符强制转换为一个p_derived
指针,那么就意味着编译器要按照derived
对象的内存布局来解释base
对象base_obj
了。但是!但是!,base
对象base_obj
是没有derived
对象的数据成员b
的,在其内存布局中,肯定也就没有b
的位置啦!那会怎么样呢?越界了呗。访问了不属于base
对象base_obj
内存区域的块,得到的自然是一个莫名其妙的值!
谈了这么多,该说说dynamic_cast
了。使用dynamic_cast
来进行转换,以上面代码为例,如果p_base
指向的是基类对象base
,那么我们通过语句dynamic_cast<derived*>(p_base)
得到的是一个NULL指针,我们可以通过判断转换后的指针是否为空,来决定是否调用派生类的成员,这样就会安全许多。