常见错误41: 静态强制类型转换----读书笔记《c++ gotchas》...
时间:2010-08-12 来源:lzueclipse
此处指的是static_cast,reinterpret_cast,const_cast以及旧式强制类型转换。
静态强制类型转换的结果往往一开始能够正确运作,但对于未来调整了对象类型布局信息的代码缺乏适应。
不要对抽象数据类型做强制类型转换,尤其是不要在一个继承谱系中的抽象数据类型做强制类型转换。
class B {
public:
virtual ~B();
virtual void op1() = 0;
};
class D1 : public B {
public:
void op1();
void op2();
virtual int thisop();
};
写一个充作工厂的函数,用以产生某种B的动态对象。
一开始,我们只有一个派生类,所以很简单:
B *getAB() { return new D1;};
下面的转换很糟糕,本来应该使用dynamic_cast。
B *bp = getAB();
D1 *d1p = static_cast<D1 *>(bp);//很糟糕
d1p->op1();
d1p->op2();
int a = d1p->thisop();
新的派生类会被加入,工厂函数也随之会升级:
class D2 : public B {
public:
void op1();
void op2();
virtual char thatop();
};
//…
B *getAB() {
if(rand() & 1)
return new D1;
else
return new D2;
}
由于使用的是静态强制类型转换,就会强迫编译器关闭了任何可能进行的诊断。
B *bp = getAB();//gets a D2
D1 *d1p = static_cast<D1 *>(bp);//D2类型强制转换为D1类型
d1p->op1();//#1调用D2::op1!!!
d1p->op2();//#2调用D1::op1
d1p->thisop();//#3调用D2::thatop!!!
标#1的那行代码对D1对象的虚成员函数做调用。
标#2的那行代码对D1对象的非虚成员函数做调用。
标#3的那行代码,
就静态情况而言,调用D1对象的名字叫thistop;
实际是动态的,调用了D2对象的thatop。
太诡异了,这种不可控的代码还是别写了。
对于使用了静态强制类型的转换,Scott Meyers说,“意味着你和编译器之间的契约被撕毁了。”
你告诉编译器,“少废话,按我说的来。”