Fork me on GitHub Fork me on GitHub

EC读书笔记系列之10:条款16、17

条款18 让接口容易被正确使用,不易被误用

记住:

★“促进正确使用”的办法包括接口的一致性,以及与内置类型的行为兼容

★“阻止误用”的办法包括建立新类型限制类型上的操作束缚对象值,以及消除客户的资源管理责任(即类的设计者应先发制人)。

★tr1::shared_ptr支持定制型删除器。这可防范DLL问题,可被用来自动解除互斥锁等等。

--------------------------------------------------------------------------

C++的接口包括:function接口、class接口、template接口......

接口的理想情况:若客户企图使用某个接口而却没有获得他所预期的行为,应让这个代码通不过编译;若代码通过了编译,它的作为就该是客户所想要的。

 

a 通过导入新类型来预防接口被误用:

1 class Date {
2     public:
3         Date( int month, int day, int year );
4         ...
5 };
6 客户易犯错误:
7 Date d( 30, 3, 1995 );  //传递参数次序错误
8 Date d( 2, 30, 1995 );  //传递一个无效的月份或天数

可以通过导入简单的外覆类型(即建立新类型)来解决:

struct Day {
    explicit Day( int d ):val(d) {} //结构体中也可以使用成员初始化列表,                                //涨姿势了!!!
    int val;
};

struct Month {
    explicit Month( int m ):val(m) {}
    int val;
};

struct Year {
    explicit Year( int y ):val(y) {}
    int val;
};
Date class改为:
class Date {
    public:
        Date( const Month &m, const Day &d, const Year &y );
        ...
};
使用时:
Date d( Month(3), Day(30), Year(1995) );

b 通过限制对象值来预防接口被误用:

如预先定义所有有效的Months:
class Month {
    public:
        static Month Jan() { return Month(1); } //返回有效月份
        static Month Feb() { return Month(2); } //同上
        ...
    private:
        explicit Month( int m );    //阻止生成新的月份,这是月份专属数据
};
使用时:
Date d( Month::Mar(), Day(30), Year(1995) );

c 通过限制类型上的操作来预防接口被误用:

  如:常见的限制是加上const。

d 消除客户的资源管理责任(即类的设计者应先发制人):

  对于如下语句:

    Investment* createInvestment();    //此函数返回的是dumb ptrs

     客户可将其返回值置入智能指针,因而将delete责任推给智能指针,但万一客户忘记就完了,此时应先发制人,就令上面函数返回一个智能指针:

std::tr1::shared_ptr<Investment> createInvestment() {

  //建立一个null shared_ptr并以getRidOfInvestment为删除器
    std::tr1::shared_ptr<Investment> retVal( static_cast<Investment*>(0), getRidOfInvestment );
    
    retVal = ...;  //令retVal指向正确对象
    return retVal;
}

  shared_ptr有个好的性质是:它会自动使用它的“每个指针专属的删除器”,因而消除另一个潜在的客户错误:cross-DLL problem。这个问题发生于“对象在DLL中被new创建,却在另一个DLL内被delete销毁”。在许多平台上,这一类“跨DLL之new/delete成对运用”会导致运行期错误。shared_ptr无这个问题,∵它缺省的删除器是来自“tr1::shared_ptr诞生所在的那个DLL”的delete。

 

shared_ptr比原始指针大且慢,而且使用辅助动态内存。在许多应用程序中这些额外的执行成本并不显著,然而其“降低客户错误”的成效却相当显著(意指性价比很高)。

 

条款19 设计class犹如设计type

记住:

★class的设计就是type的设计。在定义新的type之前,请确定你已经考虑过本条款覆盖的所有讨论主题

 

posted @ 2015-11-05 09:26  墨城烟雨  阅读(198)  评论(0编辑  收藏  举报