zoukankan      html  css  js  c++  java
  • Effective C++ Item 27 少做转型操作

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie


    todo Item34


    旧式转型
    (T) expression 或 T (expression)
    新式转型
    const_cast<T>(expression)
    通常被用来将对象的常量性转除(cast away the constness)
    dynamic_cast<T>(expression)
    运行“安全向下转型”,也就是用来决定某对象是否归属继承体系中的某个类型。
    reinterpret_cast<T>(expression)
    运行低级转型 //不太懂??


    static_cast<T>(expression)
    强迫隐式转换


    //旧式转型与新式转型
    class Widget{
    public:
    	explicit Widget(int size);
    	//...
    }
    void soSomeWork(const Widget &w);
    doSomeWork(Widget(15)); //以一个int加上“函数风格”的转型动作创建一个Widget.
    doSomeWork(static_cast<Widget>(15)); //以一个int加上“C++风格”的转型动作创建一个Widget
    

    class Base{...};
    class Derived: public Base{...};
    Derived d;
    Base *pb = &d;
    有时候上述两个指针值并不同样 。可能会有个偏移量在执行期被施行于Derived *指针上。


    对象的布局方式和它们的地址计算方式随编译器的不同而不同。


    经验:假设能够,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts。假设有个设计须要转型动作,试着发展
    无需转型的替代设计
    演示样例1:

    class Window{ //base class
    public:
    	virtual void onResize(){...} //base onResize 实现代码
    	//...
    };
    
    
    class SpecialWindow: public Window{ //derived class
    public:
    	virtual void onResize(){
    		static_cast<Window>(*this).onResize(); //derived onResize 实现代码。将*this转型为Window,然后调用其 onResize。 错误
    											   //onResize 操作的是转型生成的暂时对象的数据
    		//... 这里进行 SpecialWindow 专属行为
    	}
    }

    纠正
    class SpecialWindow: public Window{
    public:
    	virtual void onResize(){
    		Window::onResize(); //调用Window::onResize作用于*this身上
    	}
    }

    演示样例2:之所以须要 dynamic_cast ,一般是由于你想在一个你认定为derived class 对象身上运行 derived class操作函数。但你的手上却仅仅有一个
    “指向base”的pointer或reference。你仅仅能靠它们来处理对象。
    class Window {...};
    class SpecialWindow: public Window{
    public:
    	void blink();
    	//...
    };
    
    
    typedef std::vector<std::tr1::shared_ptr<Window> > VPW;
    VPW winPtrs;
    //...
    for(VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter){
    	if(SpecialWindow *psw = dynamic_cast<SpecialWindow*> (iter->get())) //不希望使用 dynamic_cast,由于很多实现版本号运行速度相当慢
    		psw->blink();
    }

    纠正1:使用类型安全容器。使用容器并在当中存储直接指向 derived class 对象的指针。消除了“通过 base class 接口处理对象”的须要。


    只是这样的做法无法在同一个容器里存储指针“指向全部可能之各种Window派生类”。

    假设真要处理多种窗体类型,须要多个容器。

    typedef std::vector<std::tr1::shared_ptr<SpecialWindow> >VPSW;
    VPSW winPtrs;
    //...
    for(VPSW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter){
    	(*iter)->blink();
    }


    纠正2:将 virtual 函数往继承体系上方移动。在base class 内提供 virtual 函数做你想对各个 Window 派生类做的事。
    class Window{
    public:
    	virtual void blink(){} //缺省实现代码 “什么也没做”。
    						   //<span style="color:#ff0000;">Item 34 --> </span>
    	//...
    };
    class SpecialWindow: public Window{
    public:
    	virtual void blink(){...}; //在此class内。blink做某些事
    	//...
    };
    
    
    typedef std::vector<std::tr1::shared_ptr<Window> > VPW;
    VPW winPtrs;
    //...
    for(VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter){
    	psw->blink();
    }





  • 相关阅读:
    leetcode回溯总结
    排序算法详解
    Java核心基础知识泛型
    leetcode贪心算法
    Linux虚拟机配置及安装Redis
    HJ6质数因子
    冒泡排序(升序)
    动态规划 背包问题
    配置mycatschema.xml
    HJ106字符逆序
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/7159267.html
Copyright © 2011-2022 走看看