条款27:尽量少做转型动作

首先是C++提供的四种转型操作:

1. const_cast:常量性的转除。
2. dynamic_cast:安全的向derived class进行转型,可能会带来很高的开销
3. reinterpret_cast:低级转型,例如可讲pointer转成int,不建议使用
4. static_cast: 强迫隐式转换,例如int to const int,int to double, 但是const int 到 int 只有const_cast能做到。
在我们面前经常出现的一种使用情况是,像下面这样:
 1 class Window{
 2 public:
 3     virtual    void onResize(){...}
 4     ...
 5 };
 6 class SpecialWindow: public Window{
 7 public:
 8     virtual void onResize(){
 9         static_cast<Window>(*this),onResize();
10         ...
11     }
12     ...
13 }
但是实际上上面的副本不能如愿以偿的调用其基类部分的onResize(),其事实上调用的是SpecialWindow的基类部分的副本的的单独的onResize,实际上和SpecialWindow的resize没有什么关系。这时,如果SpecialWindow本身也尝试去修改SpecialWidnow的非基类部分的话,那么对象就会进入一种伤残的状态.其基类部分没有进行必要的修改,但是派生类单独的部分却经历了修改,这样对象就会进入一种伤残的状态.
其实调用基类的Resize的正确方法根本就不需要用到转型操作:
class SpecialWindow:public Window{
public:
    virtual void onResize(){
        Window::onResize(){
            .......
        }
        ...
    }
};
再论dynamic_cast,记住一般起调用带来的开销还是比较大的。而一般需要dynamic_cast的主要情况是,只拥有一个base class 指针的情况下,想要对derived class进行单独的处理。一般有两种方式可以替代dynamic_cast达到这种效果.
第一种方法是取一个容器并在里面存储,直接指向derived class对象的指针(往往是智能指针)。
typedef vector<shared_ptr<SpecialWindow>> VPSW;
VPSW windPtrs;
...
for(VPSW::iterator iter = windPtrs.begin(); 
    iter != windPtrs.end(); ++iter){
    iter->blink();
}
还有一种方法就是,将虚函数从derived class向上再延伸一层,这样,直接使用Base class 的指针,就可以调用derived class的函数。
记住,优秀的代码是很少使用转型操作的,应该尽可能的隔离转型操作。
小结:
1. 如果可以应该尽量减少转型的使用,尤其是dynamc_cast(其会消耗很多的资源)。
2. 如果需要转型,那么至少应该将他隐藏起来,例如放置到某个函数内使用。
3. 如果使用转型,那么一定要使用新式转型。
posted @ 2015-10-10 16:02  eversliver  阅读(398)  评论(0编辑  收藏  举报