Effective 系列读书笔记
Tip
在开发任何库前,先去调研一下别人是怎么做的,看看 STL/QT/Boost。
二、构造/析构/赋值运算
2.3 别让异常逃离析构函数
1 | class DBConn |
以上可以保证即使用户操作错误也不会抛出异常(可以提醒用户手动解决),不抛出异常便不会影响程序的结束。
四、设计与声明
4.3 考虑写出一个不抛异常的 swap 函数
1 | // Called File |
理一下 C++ 编译器的查找逻辑:
- 发现 Call File 中的 swap() 调用;
- 全局查找 swap()(没找到对应的);
- 查找 T 所在的 namespace 中的 swap()(找到);
- namespace WidgetStuff 中的 swap 函数调用 Widget 的 swap();
- 使用 std::swap()。
以上便能实现对 swap() 的偏特化。
5.5 区分接口继承和实现继承
- 实现继承代表你确定该方法一定需要被重载,子类的实现是完全不一样的;
- 接口继承意味着你确定子类一定会有这个方法,但是不确定会不会有特例,此时你应该提供一个普适的方法;
- 不继承则是表示所有子类都统一使用同一个实现。
- 对于实现继承,应该将函数声明为 public 纯虚函数;
- 对于接口继承,应该将函数声明为 public 纯虚函数,同时提供一个 protected 的普适方法供子类在重载虚函数时调用;
- 对于不继承,应该将函数声明为 public non-virtual 函数。
6.1 Strategy design patterns
尝试通过 std::function 去完成它吧。
用代理类来解决一些问题
Lazy Expression Evaluation and Over-eager Evaluation
- 对于调用不多的,可以用 Lazy Expression Evaluation,用到时再赋值/计算。
- 相反对于调用多的,可以通过 Over-eager Evaluation 来提前计算,具体方法一般是牺牲空间储存一些实时计算的值,或者像 vector 扩容一样。
内存管理
慎重的选择容器
vector
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment