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

一. 内容

  1. 准则:如果客户使用某个接口通过了编译,那么它的行为就是应该是客户想要的
  2. 所以我们应该考虑客户可能会遇到什么样的错误
  3. 一个例子
    class Date {
    public:
        Date(int mMonth,int mDay,int mYear):
        Month(mMonth),Day(mDay),Year(mYear){}
    private:
        int Month;
        int Day;
        int Year;
    };
    inline void BeginPlay() {
        Date DateOne(30,3,1995);//oh,应该是3,30
        Date DateTwo(2,30,1995);//oh,应该是3, 30或者不存在2,30
    }
    
    这些示例可能看起来有些愚蠢,但是它们并不罕见。
  4. 这些客户端错误可以通过导入新的类型而获得预防。
    struct  Month {
        explicit Month(int mValue):Value(mValue){}
        int Value;
    };
    
    struct  Day {
        explicit Day(int mValue):Value(mValue){}
        int Value;
    };
    
    struct  Year {
        explicit Year(int mValue):Value(mValue){}
        int Value;
    };
    class DatePro {
    public:
        DatePro(const Month& mMonth,const Day&mDay,const Year& mYear):
    Month(mMonth),Day(mDay),Year(mYear){}
    private:
        Month Month;
        Day Day;
        Year Year;
    };
    inline void BeginPlayTwo() {
        DatePro DateOne(30,3,1995);//错误,不正确的类型
        DatePro DateTwo(Month(3),Day(30),Year(1995));//ok,类型正确
    }
    
    令Month,Day,Year成为成熟且经充分锻炼的 Classes 或者 Structs,对预防接口被误用有神奇效果。
  5. 一旦类型正确,有时候限制其取值是合理的。
    class  LimitedMonth {
    public:
        static LimitedMonth Jan(){return LimitedMonth(1);}
        static LimitedMonth Feb(){return LimitedMonth(2);}
        static LimitedMonth Mar(){return LimitedMonth(3);}
        static LimitedMonth Apr(){return LimitedMonth(4);}
        static LimitedMonth May(){return LimitedMonth(5);}
        static LimitedMonth Jun(){return LimitedMonth(6);}
        static LimitedMonth Jul(){return LimitedMonth(7);}
        static LimitedMonth Aug(){return LimitedMonth(8);}
        static LimitedMonth Sept(){return LimitedMonth(9);}
        static LimitedMonth Oct(){return LimitedMonth(10);}
        static LimitedMonth Nov(){return LimitedMonth(11);}
        static LimitedMonth Dec(){return LimitedMonth(12);}
    private:
        explicit LimitedMonth(int mValue):Value(mValue){}
        int Value;
    };
    
  6. 预防客户错误的另一个方法是:限制类型内什么事情可做,什么事情不能做。常见的方式是加上 const,如条款3。
  7. 还有一个一般性准则是:除非有好理由,否则尽量令接口行为和内置接口行为保持一致。比如 STL 容器的接口都十分一致,这使得它们可以被容易的调用。
  8. 任何接口如果要求客户必须记得做某些事情,就存在不正确使用的隐患。条款13在获取资源返回的是原始指针,假如客户忘记使用智能指针进行管理,怎么办呢?最好的做法是先发制人,令获取资源的接口返回智能指针。
    而对于不同的资源,智能指针默认的资源释放行为可能不适用,这也应该提前为返回的智能指针写好删除函数,避免客户误操作。
    shared_ptr 有个比较好的性质就是,自动使用它专属的删除函数,消除了 cross-DLL 问题:对象在动态连接程序库(DLL)被 new 创建,却在另一个 DLL 内被另一个delete销毁。shared_ptr 保证对象会使用原来所在单元的 delete。

二. 总结

  1. 好的接口很容易被正确使用,不容易被误用。你应该在你的所有接口中努力达成这些性质。
  2. 促进正确使用的方法包括接口的一致性,以及与内置类型的行为兼容。
  3. 阻止误用的方法包括建立新类型,限制类型上的操作,束缚类型值,以及消除客户的资源管理责任。
  4. trl::shared_ptr 支持定制型删除器(custom deleter)。这可防范 DLL 问题,可被用来自动解除互斥锁(mutexes,见条款14)等等。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值