C++设计与声明——让接口容易被正确使用
一个简答易错的例子
class Date { public Date(int month,int day,int year); }
一年后使用这个接口的时候,写了Date d(15,10,2015)或者Date d(2015,10,15),准确的应该是Date d(10,15,2015),欧,多么低级的错误,花了我一个早上的时间去调试这个bug。
解决的方法
- 为参数声明自定义类型
struct Day { explicit Day(int d):val(d) {} int val; }; struct Month { explicit Month(int d):val(d) {} int val; }; struct Year { explicit Year(int d):val(d) {} int val; }; class Date { public: Date(const Month& m,const Day& d,const Year& y); }; Date d(30, 3, 1995); //wrong Month m(10); Day m(15); Year y(2015); Date(y, m, d); //wrong Date(m, d, y); //right
这样子声明类型会很麻烦,但是对“接口被误用”却又神奇的疗效
- 使用预先定义的类
class Month { public: static Month Jan() { return Month(1); } ... private: explicit Month(int m); ... };
通过函数返回我们需要的月份,保证参数的正确性。
PS:上面使用函数返回,是为了保证使用的月份实例已经初始化
- 自定义类型与内置类型保持一致
常见的方法有:加上const。再来一个易错的例子
class INT { public INT(int); INT opeaator=(INT); INT operator*(INT); int val; }; if(a*b = c) {...}
我们重新定义了系统的int类型,却发现,在a * b = c成功地通过了编译阶段,这个时候要想不进入if下的程序块真的是难上加难,这很明显违背我们的初衷。假如operator返回的是const,那么就会限制a b = c的执行。其实,这只是与内置类型的int符合罢了。所以,自定义的type应该尽量内置类型保持一致,除非我们有个好理由(其实一般我们也找不到这种理由)。
- 保持接口一致化
假如string使用Length,List使用size返回内部的对象个数,你是不是每次使用的时候都要考虑一下要使用Length还是size?假如不想自己的心灵饱受折磨,请保持功能一致的接口使用方法一致。
- 在客户之前预防客户的错误
假如createInvestment()返回一个Investment类型的指针给客户,谁也无法保证客户使用完了会正确地释放内存。所以较佳的做法是,先发制人,强迫客户使用智能指针,将返回值修改为std::tr1::share_ptr< Investment >createInves()给客户,这基本消除了发生内存泄露的可能性。
假如客户希望通过getRidOfInvestment()来删除指针,但却希望客户自己完成这件事,那又多了一个通往错误的大门。我们可以在返回智能指针前就先指定好删除器,以免客户遗忘。
std::tr1::shared_ptr< Investment> createInvestment() { std::tr1::share_ptr< Investment> retVal(static_cast< Invesment*>(0), getRidOfInvestment); retVal = ...; //令retVal指向正确的对象 return retVal; }
上面的例子中,就算用户忘记了释放内存,最后智能智能share_ptr也会根据getRidOfInvestment正确地释放,从而减少了内存泄露的可能性。
实际上,使用了share_ptr的好处不仅仅如此。当使用了dll的时候,假如在一个dll中获得了指针,在另一个dll中依然能通过原来的dll对指针进行删除。从而用户无需在意cross dll problem的问题。
原文地址:https://www.cnblogs.com/suimeng/p/4884102.html
相关推荐
-
【vn.py】CTP首次登陆修改密码 之 接口调用法 c/c++
2020-6-15
-
动态修改 C 语言函数的实现 c/c++
2019-3-30
-
UICollectionView 固定行距列表左排: 来一个自定制 Layout c/c++
2019-6-22
-
Ceph v12.2 Luminous 文件存储(CephFS)搭建 c/c++
2019-3-28
-
GDB的断点调试 c/c++
2019-3-30
-
分布式rpc框架ice学习之helloworld篇 c/c++
2019-4-1
-
手动删除木马程序 c/c++
2019-10-7
-
C++ 开发 PHP 7 扩展之模块入口定义 c/c++
2019-3-28
-
数据结构与算法之基础排序算法 c/c++
2019-3-28
-
动态分配那些事儿 c/c++
2019-11-2