关于static_cast和dynamic_cast:
1,附详细代码并解释,总算搞清楚了!
class base{
public:
virtual void foo(){}//用于添加虚函数表vtable
int a;
};
class left_hand:public base{
};
class right_hand:public base{
};
class derive:public left_hand,public right_hand{
};
class unrelated{//一个毫不相关的类
public:
virtual void Foo(){}
};
void main()
{
left_hand* pl = new derive;
base* pb = pl;//隐式类型转换,可以用static_cast代替,无区别,安全的转换
derive* pd = dynamic_cast<derive*>(pl);//这里会给出警告,若用static_cast可
//编译成功,因为2指针存在继承关系,运行
right_hand* pr = new derive; //也能成功,因为pl确实指向的是derive
pd = static_cast<derive*>(pr); //这里用于测试多个基类的无差异性
right_hand* pr2 = new right_hand; //注意这里,pr2指向的不是derive
pd = dynamic_cast<derive*>(pr); //这里不管用static_cast还是dynamic_cast
delete pl; //都能编译成功,但运行时,若用static_cast
delete pr; //极有可能使程序崩溃,用dynamic_cast则造
delete pr2; //成pd为NULL,慎用!
unrelated* unr;
pd = dynamic_cast<derive*>(unr);//only warning:C4541
left_hand* lh;
right_hand* rh;
lh = static_cast<left_hand*>(rh);//compiling time check,errorC2440
lh = dynamic_cast<left_hand*>(rh);//only warning:C4541
//if:
left_hand* lh2 = new derive;
right_hand* rh2;
rh2 = dynamic_cast<left_hand*>(lh2);//运行时也能成功转换
delete lh2;
}
static_cast<type>(expression)用于一般转换,代替隐式类型转换,以及基类指针到子类指针转换,只进行编译器检查(只要两个指针存在public继承关系,编译均能成功,而不管指针指向的确切类型),但在运行时有可能发生错误(当基类指针指向的确实不是要转换为的子类时),造成程序崩溃;dynamic_cast<type>(expression)用于基类到子类指针的转换,但dynamic_cast只进行运行时检查(通过vtable获得运行时类型信息,这就是必须要有虚函数的原因),如果指针指向的确切类型可以转换(如基类ptr确实指向要转换的子类,或者子类的派生类),则转换成功,否则返回NULL.所以在进行dynamic_cast转换时最好加上异常处理或者判断指针是否为NULL的语句。