Effective C++——条款18(第4章)
2015-09-04 18:24
309 查看
第4章 设计与声明
Designs and Declarations所谓软件设计,是"令软件做出希望它做的事情"的步骤和做法,通常以颇为一般性的构想开始,最终演变成十足的细节,以允许特殊接口(interfaces)的开发.这些接口而后必须转换为C++声明式.最重要,最适合的一个准则是:"让接口容易被正确,不容易被误用".
条款18: 让接口容易被正确使用,不易被误用
Make interfaces easy to use correctly and hard to use incorrectlyfunction接口,class 接口,template 接口...每一种接口都是客户与代码互动的手段.欲开发一个"容易被正确使用,不容易被误用"的接口,首先必须考虑客户可能做出什么样的错误.假设为一个用来表现日期的 class 设计构造函数:
class Date { public: Date(int month, int day, int year); ... };乍看之下这个接口通情达理,但它的客户很容易犯下至少两个错误,第一,他们也许会以错误的次序传递参数:
Date d(30, 3, 1995); // error!应该是"3,30"而不是"30,3"第二,他们可能传递一个无效的月份或天数:
Date d(2, 30, 1995); // error!应该是"3,30"而不是"2,30"许多客户端错误可以因为导入新类型而获得预防.在防范"不值得拥有的代码"上,类型系统是很好的办法.下面导入简单的外覆类型来区分天数,月份和年份,然后于Date构造函数中使用这些类型:
struct Day { explicit Day(int d) : val(d) {} int day; }; struct Month { explicit Month(int m) : val(m) {} int val; }; struct Year { explicit Year(int y) : val(y) {} int val; }; class Date { public: Date(const Month &m, const Day &d, const Year &y); ... }; Date d(30, 3, 1995); // error! Date d(Day(30), Month(3), Year(1995)); // error! Date d(Month(3), Day(30), Year(1995)); // OK!令Day, Month和Year成为成熟且充分锻炼的 class 并封装其内部数据,比简单使用上述的 struct 好(详见条款22).
一旦正确的类型就定位,限制其值有时候是合理的.例如:
class Month { public: static Month Jan() { return Month(1); } // 函数,返回有效月份 ... // 这些是函数而非对象 static Month Dec() { return Month(12); } private: explicit Month(int m); // 阻止生成新的月份 ... }; Date d(Month::Mar(), Day(3), Year(1995));如果"以函数替换对象,表现某个特定月份"让人感觉诡异,但是考虑到non-local static 对象的初始化次序有可能出问题(详见条款4),就感觉合理了.
预防客户错误的另一个办法是,限制类型内什么事可做,什么事不能做.常见的限制就是加上 const.例如条款3曾经说明为什么"以const修饰operator*的返回类型"可阻止客户因"用户自定义类型"而犯错:
if (a * b = c) ...一个一般性的准则是"尽量令自定义types的行为与内置types一致".
注意:
好的接口很容易被正确使用,不容易被误用.应该在所有接口中努力达成这些性质.
"促进正确使用"的办法包括接口的一致性,以及与内置类型的行为兼容.
"阻止误用"的办法包括建立新类型,限制类型上的操作,束缚对象值,以及消除客户的资源管理责任.
相关文章推荐
- 贝格尔编排法之C++版
- C++输入输出知识
- 为什么C++ 不叫++C?
- C++入门经典 笔记 (第十三章)高级引用和指针
- C语言实现栈操作
- 华为OJ题库-C++实现蛇形矩阵
- [JNI] Java 调用 C++ dll
- JNI开发之 c++输出日志到Logcat
- c++虚函数机制
- C++基础---函数指针
- python类变量与 C++的静态变量并不等效
- C++基础---有返回值类型函数(指针函数)
- 继承关系中的虚函数表
- C++基础---有返回值类型函数(返回引用类型)
- C++中的虚函数详解
- C++标准库异常类
- C++基础---有返回值类型函数(返回非引用类型)
- stl内存池学习
- extern "C"的用法解析
- C++堆栈的比较