Effective C++ 学习笔记(二)

Effective C++ 学习笔记(二)

  • 总共54个条款,分为9个 部分
    1. 让自己习惯C++
    2. 构造/析构/赋值运算
    3. 资源管理
    4. 设计与声明
    5. 实现
    6. 继承与面向对象
    7. 模板与泛型编程
    8. 定值new和delete
    9. 杂项讨论

设计与声明

  • 让接口容易被正确使用,不易被误用
  • 设计class犹如设计type
    1. 新type的对象应该如何被创建和销毁?
      • 构造函数
      • 析构函数
      • 内存分配和释放函数operator new、operator new[]、operator delete、operator delete[]
    2. 对象的初始化和对象的赋值该有什么样的差异?
      • 构造函数
      • 赋值操作符
    3. 新type的对象如果被passed by value,意味着什么?
      • copy构造函数用来定义一个type的pass-by-value该如何实现
    4. 什么是新type的“合法值”?
      • 对成员函数必须进行的错误检查工作
      • 抛出的异常
      • 函数异常明细列表
    5. 新的type需要配合某个继承图系?
    6. 新type需要什么样的转换?
      • 隐式和显式转换函数
    7. 什么样的操作符和函数对此新type而言是合理的?
    8. 什么样的标准函数应该驳回?
      -被声明为private的部分
    9. 谁该取用新type成员?
    10. 什么是新type的“未声明接口”?
    11. 新type有多么一般化?
    12. 是否真的需要新的type?
  • 宁以pass-by-reference-to-const替换pass-by-value
    1. 尽量以pass-by-reference-to-const替换pass-by-value。前者通常比较搞笑,并可避免切割问题。
    2. 以上规则并不适用于内置类型,以及STL的迭代器和函数对象。对他们而言,pass-by-value往往比较适当。
  • 必须返回对象时,不要返回reference
    绝对不要返回pointer或reference指向一个local stack对象,或返回reference指向一个heap-allocated对象,或返回pointer或reference指向一个local static对象而言有可能同时需要多个这样的对象。
  • 将成员变量声明为private
  • 以non-member 和 non-friend 函数替换member 函数
  • 如果需要为某个函数的所有参数(包括this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member。

实现

  • 尽量延后变量定义式的出现时间
  • 尽量少做转型动作
    1. const_cast
    2. dynamic_cast
    3. reinterpret_cast
    4. static_cast
  • 确保异常安全
    1. 任何使用动态内存的东西(如STL的容器)如果无法找到足够内存以满足需求,通常便会跑出一个bad_alloc异常。
  • Inline函数
  • 将文件的编译依存关系降至最低
    1. 支持“编译依存性最小化”的一般构想是:相依于声明式,不要相依与定义式。基于此构想的两个手段是Handle classes和Interface classes。
    2. 程序库头文件应该以“完全且仅有声明式”(full and declaration-only forms)的形式存在。这种做法不论是否设计templates都是用。

继承与面向对象设计

  • 确定public继承塑模出is-a关系
    public继承意味着适用于基类身上的每一件事情一定也适用于继承类身上,因为每一个继承类对象也都是一个基类对象。
  • 避免遮掩继承而来的名称
    1. derived classes内的名称会遮掩base classes内的名称。在public继承下从来没有人希望如此。
    2. 为了让被遮掩的名称再见天日,可使用using声明式或inline转交函数(forwarding functions)。
  • 区分接口继承和实现继承
    1. 接口继承和实现继承不同。在public继承之下,derived classes总是继承base class的接口。
    2. 纯虚函数只具体指定接口继承。
    3. 非纯虚函数具体制定接口继承及缺省实现继承。
    4. 非虚函数具体指定接口继承以及强制性实现继承。
  • 考虑virtual函数以外的其他选择
    1. 籍由Non-Virtual Interface手法实现Template Method设计模式
    2. 籍由Function Pointers实现Strategy设计模式
    3. 籍由tr1::function完成Strategy设计模式
      • 使用NVI手法,那是Template 设计模式的一种特殊形式。它以public non-virtual成员函数包裹较低访问性(private或protected)的virtual函数。
      • 将virtual函数替换为“函数指针成员变量”,这是Strategy模式的一种分解表现形式。
      • 以tr1::function成员变量替换virtual函数,因为允许任何可调用物(callable entity)搭配一个兼容于需求的签名式。这也是Strategy模式的某种形式。
      • 将继承体系内的virtual函数替换为另一个继承体系内的virtual函数。这是Strategy模式的传统实现手法。
  • 绝不重新定义继承而来的non-virtual函数
  • 绝不重新定义继承一个带有缺省值的virtual函数
  • 通过复合塑模出has-a或“根据某物实现出”
  • 明智而审慎地使用private继承
  • 明智而审慎地使用多继承(MI)
    1. 多重继承比单一继承复杂。他可能导致新的歧义性,以及对virtual集成的需要。
    2. virtual继承会增加大小、速度、初始化(及赋值)复杂度等等成本。如果virtual base classes不带任何数据,将是最具实用价值的情况。
    3. 多长继承的确有正当用途。其中一个情节设计“public继承某个Interface class”和“private继承某个协助实现的class”的两相组合。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值