面向对象编程
- 面向对象编程是一种设计思想,关键是抽象和封装,而继承和多态是衍生出的特性,不完全符合现实世界。在C++里应当少用继承和虚函数,降低对象的负担,绕过那些难懂易错的陷进。
- 使用特殊标识符final可以禁止类或虚函数被继承,简化类的层次关系。
- 类有六大基本函数,对于重要的构造/析构函数,可以使用“=default"来显式要求编译器使用默认实现。
- 使用委托构造成员变量初始化等特性可以让创建对象的工作更加轻松。
- 使用using为类型起别名,既能够简化代码,又能够适应将来的变化。
自动类型推导
- 自动类型推导是给编译器下的命令,让编译器去计算表达式的类型,然后将类型返回给程序员。
- auto用于初始化时的类型推导,总是推导出值类型,也可以加上修饰符推导出新的类型。它的规则比较好理解,用法也简单,应该尽量使用。
- C++17为auto增加了结构化绑定的功能,可以自动推导出一组变量的类型,用来拆解有结构的对象(如pair/tuple),简化代码。
- decltype使用类似函数调用的形式计算表达式的类型,能够用在任意场合,因为它就是一个编译阶段的类型。
- decltype能够推导出表达式的精确类型,但写起来比较麻烦,在初始化时可以采用C++14新增的decltype(auto)的简化形式。
- 因为auto/decltype不是硬编码的类型,所以用好它们可以让代码更清晰,降低后期维护的成本。
变量与常量
- const可以给任何对象附加上只读属性,以保证安全。
- const可以修饰引用和指针,”const &"可以引用任何类型,是用作函数入口参数的最佳类型。
- const还可以修饰成员函数,表示函数是只读的,const成员函数不能修改对象的状态,const对象只能调用const成员函数。
- volatile表示变量可能会以”难以察觉“的方式被修改,禁止编译器优化,会影响性能,应当少用。
- multable用来修饰成员变量,表示允许const成员函数修改该变量。multable成员变量的改动不影响对象的常量性,但要小心,误用会导致对象损坏。
- constexpr是真正的编译器常量,可以修饰表达式和函数,用于编译器的计算和优化。
const | 非const | |
对象(实例) | (const T)对象只读,只能调用const成员函数 | 可以修改对象,调用任意成员函数 |
引用 | (const T&) 引用对象只读,只能调用const成员函数 | |
指针 | (const T*) 指针指向的对象只读,只能调用const成员函数 | |
成员函数 | (func()const) 只能修改multable成员变量,其他不允许修改 | 可以修改任意成员变量 |
尽可能多用const,让代码更安全
异常
- 异常是针对错误码的缺陷而设计的,它不能被忽略,而且可以”穿透“调用栈,逐层传播到其他地方去处理。
- 使用try-catch机制处理异常能够分离正常业务逻辑与错误处理逻辑,让代码更清晰。
- throw可以抛出任何类型的异常,但最好使用标准库里定义的exception类。
- 全用或全不用异常处理错误都不可取,应该合理分析,适度使用,降低异常处理的成本。
- 关键字noexcept用于标记函数不抛出异常,从而让编译器更好地进行优化。
函数式编程
- lamdba表达式是一个闭包,能够像函数一样被调用,像变量一样被传递。
- 可以使用自动类型推导存储lambda表达式,但C++鼓励尽量就地匿名使用lambda表达式,缩小作用域。
- lambda表达式使用"[=]"的方式按值捕获,使用''[&]''的方式按引用捕获,空的''[]''则表示无捕获。
- 捕获时必须要注意使用外部变量的生命周期,方式变量失效,尽量显示捕获。
- C++14后可以使用泛型的lambda表达式相当于简化的模板函数