文章目录

  • 友好的接口设计
  • member与non-member函数设计
  • 不抛异常的swap函数设计

让接口容易被正确使用,不易被误用
设计class犹如设计type
宁以pass-by-reference-to-const替换pass-by-value
必须返回对象时,别妄想返回其reference
将成员变量声明为private
宁以non-member、non-friend替换member函数
若所有参数皆须类型转换,请为此采用non-member函数
考虑写出一个不抛异常的swap函数

友好的接口设计

引入类:

class Time
{public:Time();~Time();Time* createTime();...void setTime(int hour, int minute, int second);...
};

一切都是为了接口的友好,必须要考虑以下两个问题:

  • 用户可以给什么?
  • 可以给用户什么?

用户可以给什么即用户的参数怎么传递,如何通过参数的结构化设计来避免用户传参时的茫然。针对 setTime 函数:

// 普通设计
void setTime(int hour, int minute, int second) {...}// 参数结构化
struct HOUR {...} // 或 enum HOUR {...}
struct MINUTE {...} // 或 enum MINUTE {...}
struct SECOND {...} // 或 enum SECOND {...}
void setTime(HOUR hour, MINUTE min, SECOND sec);

通过对参数封装实现输入参数限制,接口更友好。但这种设计是否必要?我不禁想起各种开源的神级软件,例如ffmpeg、vlc等等不胜枚举,参数真的是晦涩…此外,增加函数内部检查即可有效避免参数错误情况,不过如果是做开放API则遵循这些友好建议是相当不错的。
可以给用户什么如出一辙,针对 createTime 函数,创建的对象指针最后需要被释放,为了避免忘记可以将对象指针放入智能指针,但何不一开始 createTime 就直接返回智能指针呢?
唔,这种强烈交互性需求必然要求像设计C++内置type一样去设计自己的类。这对于大众码农来说当然是很高的要求了,不然何不写个自己的语言呢?
封装层面的暂且不说,来谈谈性能层面。

int compare(Time tm) {...}int compare(const Time &tm) {...}

区别在哪?Time tm 会在传递过程中产生临时变量和复制操作,而 const Time &tm 则不会产生额外变量,可以减少的性能耗费当然是尽量减少了。之前网上不少网友因为 std::string 作为参数传递为什么要传 const std::string & 而大打出手,Qt那边也有 QStringconst QString & 相同疑问,想必这样应该会对 使用引用传递替代值传递 有更加深刻的认识。
再看:

const Rational& operator*(const Rational &lhs, const Rational &rhs)
{Rational result(lhs.n * rhs.n, lhs.d * rhs.d);return result;
}const Rational& operator*(const Rational &lhs, const Rational &rhs)
{Rational *result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);return *result;
}

这些都是翻车代码,返回给用户的都是埋雷的引用。情况一的result由stack分配,函数返回时它的内存理当销毁,那要它的引用有何用?情况二的result确实由heap分配,但谁负责销毁?

member与non-member函数设计

考虑程序:

class WebBrowser
{public:...void clearCache();void clearHistory();void removeCookies();...// member封装调用void clearEverything(); // 调用clearCache、clearHistory和removeCookiesprivate:bool cleared; // 成员变量应尽量private
};// non-member封装调用
void clearBrowser(WebBrowser &wb)
{wb.clearCache();wb.clearHistory();wb.removeCookies();
}

member封装调用和non-member封装调用哪个好?non-member函数允许对WebBrowser相关机能有较大的包裹弹性,可增加WebBrowser的可延展性。
事实上,WebBrowser提供网络访问的最基本封装,而clear操作则是针对WebBrowser的业务封装,建议将这两部分的代码独立出来。而如果非要选择的话还是non-member更好些,除非提供额外的类来替代non-member的功能。
其次,变量成员都声明成 private 也并非必须,不能说 public 的改动可能波及范围大就摒弃 publicprotected 型的成员变量,在没有明确期望成员变量何时可见的时候,我们不妨使用中庸的 protected ,而当目标明确的时候,限定符的选择自然也就不会成为问题。
针对算术运算的member与non-member比较:

class Rational
{public:...const Rational operator*(const Rational &rhs) const; // member...
};// non-member
const Rational operator*(const Rational &lhs, const Rational &rhs)
{return Rational(lhs.numerator() * rhs.numerator(),lhs.denominator() * rhs.denominator());
}

此时的member并不能完全实现混合运算,而non-member声明的函数却可以:

// member
Rational oneEighth(1, 8);
Rational oneHalf(1, 2);
Rational result = oneHalf * oneEighth; // success
result = result * oneEighth; // success
result = oneHalf * 2; // success
result = 2 * oneHalf; // error// non-member
result = oneHalf * 2; // success
result = 2 * oneHalf; // success

这是因为member只是属于类的操作符重载,由类主导;而non-member对两个操作数平等对待,自然可以对所有参数进行隐式的类型转换。
总结而言:针对功能需求合理选择member与non-member函数实现。

不抛异常的swap函数设计

《Effective C++ 3th》——设计与声明相关推荐

  1. Effective C++ --4 设计与声明

    上一部分Effective C++ --3 资源管理 18.让接口容易被正确使用,不易被误用 (1)设计接口时要考虑客户可能可能做出的错误输入,如参数的形式等. 19.设计class犹如设计type ...

  2. 《Effective C++ 3th》——后记

    像<Effective C++ 3th>这类书,在C++进阶阶段必不可少.总结而言,书中内容主要分为以下几块: 减少出错的良好编程习惯/原则: 降低资源利用的有效策略: 深入理解OOP的精 ...

  3. effective java 3th item2:考虑 builder 模式,当构造器参数过多的时候

    yiaz 读书笔记,翻译于 effective java 3th 英文版,可能有些地方有错误.欢迎指正. 静态工厂方法和构造器都有一个限制:当有许多参数的时候,它们不能很好的扩展. 比如试想下如下场景 ...

  4. Effective C++ ——设计与声明

    条款18:让接口更容易的被使用,不易误用 接口设计主要是给应用接口的人使用的,他们可能不是接口的设计者,这样作为接口的设计者就要对接口的定义更加易懂,让使用者不宜发生误用,例如对于一个时间类: cla ...

  5. 《Effective C++ 3th》——继承与面向对象设计

    文章目录 Is A 确定你的public继承塑模出is-a关系 避免遮掩继承而来的名称 区分接口继承和实现继承 考虑virtual函数以外的其他选择 绝不重新定义继承而来的non-virtual函数 ...

  6. EC++学习笔记(四) 设计与声明

    条款18:让接口容易被正确使用,不易被误用 必须考虑客户可能做出什么样的错误(防御式编程) std:shared_ptr会自动使用它的"每个指针专属的删除器",消除了"c ...

  7. effective java 3th 序

    正本基本是自己翻译,翻译绝对有错误,就是这么自信,看的时候,自己注意下,如果感觉有语句不通,那么可能就是我翻译的出现了问题,可以自己翻找原文对比下. 其中自己的见解,我写在脚注中. 在 1997 年, ...

  8. 《Effective C++ 3th》——实现

    文章目录 写精简的程序 写安全的程序 写低耦合的程序 尽可能延后变量定义式的出现时间 尽量少做转型动作 避免返回handles指向对象内部成分 为"异常安全"而努力是值得的 透彻了 ...

  9. 《Effective C++ 3th》——资源管理

    文章目录 资源如何释放? 注意资源的唯一性 由使用智能指针引出的问题 以对象管理资源 在资源管理类中小心coping行为 在资源管理类中提供对原始资源的访问 成对使用new和delete时要采取相同形 ...

最新文章

  1. 高效学习方法论的学习笔记
  2. 美团配送数据治理实践
  3. k8s service服务发现详解:ipvs代理模式、服务类型
  4. ConcurrentHashMap的源码分析-JDK1.7和Jdk1.8版本的变化
  5. 连不到别人电脑的mysql_连接其他电脑mysql (转)
  6. 中南大学和中山大学计算机专业哪个好,中山大学和中南大学哪个实力更强?一字之差,一起来看看吧!...
  7. 前台setcookie之后从后台取出来_后台设置Cookie值,前台进行获取
  8. 列表应用(导航菜单)
  9. 三、JVM — 类加载过程
  10. 【面经】关于逻辑回归,面试官们都怎么问
  11. TabBars代码解读之——Visual Studio的自动化接口
  12. 数据-第17课-栈课后练习
  13. 自动化测试工具-Airtest
  14. Linux服务篇之SSH服务
  15. 免费云服务器(阿贝云服务器入门)(仅适用于windows server系统)
  16. eda交通灯控制器波形输入_EDA实验报告实验四:交通灯控制器设计
  17. 使用c语言实现后缀表达式计算器
  18. 工作中一个管理者的态度
  19. 苹果电脑怎么打印cpa准考证
  20. 实现Python Http 接口测试

热门文章

  1. 抄书问题2 (复制书稿) 单调性优化dp + 序列划分模型
  2. http响应头类型json格式整理
  3. 国密Nginx容器实战
  4. struct 结构体解析(原)
  5. 架构09 社交软件红包技术01
  6. python英语词汇读音_美式英语和英式英语音标单词发音差异区别大全
  7. C语言指针(基础篇)
  8. python魔法方法学不懂_深入学习Python之魔法方法
  9. MOS管栅极反并联二极管的作用
  10. 毕业设计 树莓派单片机墨水屏电子日历系统 - 物联网 嵌入式