<<Effective C++>>读书笔记

来源:互联网 发布:申请斯坦福大学知乎 编辑:程序博客网 时间:2024/06/06 04:03

谨以此书作为现代C++程序设计的基石

没有阅读和模板有关的章节,将已经是常识的概念没有记录

  • 使用const enum inline替换#define,便于调试。因为使用#define定义的变量不进入符号表。

  • 尽可能在所有的地方使用const

    • 重载二元运算符时,防止出现无聊的赋值行为。
    const Blas& operator+(const Blas& lhs,const Blas& rhs);if(a*b = c)
    • 尽量使用const修饰类的成员函数。前置const表示返回的变量不可修改;后置的const表示该成员函数不修改类的成员变量。

    • 在类成员函数的重载概念中,有无const可视为不同的成员。为了防止代码重复,可以借助强制转化的方法完成const -> non-const

    const char& operator[](size_t pos){    ...    return text[pos];};......char& operator[](size_t pos){    return const_cast<char&>(static_cast<const Blas&>(*this)[pos])}
  • 确定对象使用之前被初始化,主要针对暴露在全局空间的对象,解决方法:使用inline函数

inline Blas& InitBlas(){    static Blas blas();    return blas;}
  • 一个完整的现代C++类应该具有以下的动作(如果涉及到内存资源的管理,最好明确拒绝编译器补充的默认版本):

    • 构造函数,析构函数

    • copy构造函数,move构造函数

    • copy构造运算符,move构造运算符

  • 在类的声明后面加上=final表示明确拒绝派生;在成员函数后面加上=delete表示明确拒绝编译器补充。

  • 声明virtual析构函数的前提是:类中至少有一个virtual描述的成员函数,否则没有必要

  • 一定要在在析构函数中处理掉异常

  • 不在类成员的构造和析构期间调用虚函数。在派生类构造期间,virtual停留在基类阶层;在基类构造期间,virtual函数还不具有virtual属性

  • 针对资源管理类的拷贝,移动动作需要处理自我赋值移动的情况

  • 在具有派生体系的类中,需要处理派生类基类成员的复制移动情况。

Blas::Blas(const Blas& lhs) : Customer(lhs)//初始化基类{};......Blas& Blas::operator=(const Blas& lhs){    ...    Customer::operator=(lhs);    ...}
  • 使用智能指针管理资源,防止shared_ptr的环形引用,尽量向shared_ptr传入删除器

  • 内置类型除外的其他类型尽量使用pass-by-reference-to-const的方式传递。针对派生类向基类传递时,会对派生类的对象进行切割,只传递给它基类的部分。

  • 栈变量不能作为引用返回。

  • 在同一名称空间内,以non-member函数的形式向一个已成型的类制定一组接口,这样做会降低依赖度。在某种意义上,对类的私有变量制定太多的成员函数会降低封装度。试想,修改一个变量时,你需要修改几乎所有的接口函数?以non-member的形式会给予程序较高的灵活性。

class WebBrowser{    public:    ...    void clearEvenything();    ...};void clearEverything(){    wb.clearCache();    wb.clearHistory();    wb.clearCookis();}
  • 为自己的类实现一个swap函数。

  • 转型

    • 使用C++11规范的四个转型操作

    • 任何一个转型操作是在编译期间编译出运行期执行的代码。

    • 尽量避免转型操作,如果不能避免,向用户隐藏转型操作(设计角度)

  • 为了封装性,避免返回类成员的引用

  • 一定要编写异常安全的代码

  • inline

    • inline是编译期的行为,且只是对编译器的一个请求

    • 编译器不会对声明inline但是调用函数的代码进行inline

    • inline会使代码膨胀,无法随着程序库的升级而升级

  • 使用前向声明降低文件的编译依赖性

  • 确定继承关系具有明确的is-a关系

  • 注意区分虚函数的继承以及成员函数的重载。虚函数继承时,参数以及返回类型不变;重载反之。

  • 如果派生类需要覆写基类的虚函数,明确的函数后面加上override,注意区分接口继承与实现继承。

  • 虚函数不应该带有默认参数。在继承体系中,虚函数是动态确定的,而默认参数是静态绑定的。

  • 私有继承和多继承

    • 能不使用上述两种继承关系就不使用。多重继承意味着没有办法动态的确定虚函数覆写的是那个基类的虚函数;私有继承介于is-ahas-a的关系之间。
原创粉丝点击