代码改变世界

effective C++ 第五章

2011-11-20 15:57  Clingingboy  阅读(534)  评论(0编辑  收藏  举报

 

第五章:实现

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

1.转换一个explicit构造函数

class Widget {
public:
    explicit Widget(int size);
    ...

};

void doSomeWork(const Widget& w);

doSomeWork(Widget(15));                    // create Widget from int

// with function-style cast

doSomeWork(static_cast<Widget>(15));       // create Widget from int

// with C++-style cast

2.不要在子类中转换基类调用(调用了一个副本对象)

class Window {                                // base class

public:

    virtual void onResize() { ... }             // base onResize impl

    ...

};

class SpecialWindow: public Window {          // derived class

public:

    virtual void onResize() {                   // derived onResize impl;

        static_cast<Window>(*this).onResize();    //wrong cast *this to Window,
        Window::onResize();//right
        // then call its onResize;

        // this doesn't work!
        ...                                       // do SpecialWindow-

    }                                           // specific stuff
    ...
};

3.dynamic_cast的替代方案

(1)直接使用子类,避免转型…貌似废话

之前:

class Window { ... };

class SpecialWindow: public Window {

public:
    void blink();
    ...

};
typedef                                            // see Item 13 for info
    std::vector<std::tr1::shared_ptr<Window> > VPW;  // on tr1::shared_ptr
VPW winPtrs;
...
    for (VPW::iterator iter = winPtrs.begin();         // undesirable code:
        iter != winPtrs.end();                        // uses dynamic_cast

++iter) {

    if (SpecialWindow *psw = dynamic_cast<SpecialWindow*>(iter->get()))
        psw->blink();
}

之后:

typedef std::vector<std::tr1::shared_ptr<SpecialWindow> > VPSW;
VPSW winPtrs;
...
    for (VPSW::iterator iter = winPtrs.begin();        // better code: uses

        iter != winPtrs.end();                        // no dynamic_cast

++iter)
    (*iter)->blink();

2.在基类使用虚函数

3.避免在循环中大量使用dynamic_cast

条款 29:为“异常安全”而努力是值得的

提供三种异常保证:

1.基本承诺:如果异常被抛出,程序内的任何事物仍保持在有效状态下。

2.强烈保证:要么成功,要么失败。保持执行前后状态一致(通常以copy-and-swap实现)

3.不抛掷保证:承诺绝不抛出异常。

大部分函数都属于连带影响,所以很难道做到强烈保证,不抛掷保证也是如此,一旦函数复杂了,有连带影响就会如此.所以只能尽量提供基本承诺,并提供异常码.

每个函数都处理异常是一个很繁琐的处理.

条款 31:将文件间的编译依存关系降至最低

很常用的声明和定义分离开发,即每份代码都有一个接口声明和一份代码实现,个人不大喜欢这样.没必要每份代码都遵守这个规则,太死板了吧.