<<Effective C++>>读书笔记
2017-05-18 16:58
316 查看
谨以此书作为现代C++程序设计的基石
没有阅读和模板有关的章节,将已经是常识的概念没有记录
使用
尽可能在所有的地方使用
重载二元运算符时,防止出现无聊的赋值行为。
尽量使用
在类成员函数的重载概念中,有无
确定对象使用之前被初始化,主要针对暴露在全局空间的对象,解决方法:使用inline函数
一个完整的现代C++类应该具有以下的动作(如果涉及到内存资源的管理,最好明确拒绝编译器补充的默认版本):
构造函数,析构函数
copy构造函数,move构造函数
copy构造运算符,move构造运算符
在类的声明后面加上
声明virtual析构函数的前提是:类中至少有一个virtual描述的成员函数,否则没有必要
一定要在在析构函数中处理掉异常
不在类成员的构造和析构期间调用虚函数。在派生类构造期间,virtual停留在基类阶层;在基类构造期间,virtual函数还不具有virtual属性。
针对资源管理类的拷贝,移动动作需要处理自我赋值,移动的情况
在具有派生体系的类中,需要处理派生类基类成员的复制与移动情况。
使用智能指针管理资源,防止
内置类型除外的其他类型尽量使用
栈变量不能作为引用返回。
在同一名称空间内,以
为自己的类实现一个
转型
使用C++11规范的四个转型操作
任何一个转型操作是在编译期间编译出运行期执行的代码。
尽量避免转型操作,如果不能避免,向用户隐藏转型操作(设计角度)
为了封装性,避免返回类成员的引用
一定要编写异常安全的代码
inline
inline是编译期的行为,且只是对编译器的一个请求
编译器不会对声明inline但是调用函数的代码进行inline
inline会使代码膨胀,无法随着程序库的升级而升级
使用前向声明降低文件的编译依赖性
确定继承关系具有明确的
注意区分虚函数的继承以及成员函数的重载。虚函数继承时,参数以及返回类型不变;重载反之。
如果派生类需要覆写基类的虚函数,明确的函数后面加上
虚函数不应该带有默认参数。在继承体系中,虚函数是动态确定的,而默认参数是静态绑定的。
私有继承和多继承
能不使用上述两种继承关系就不使用。多重继承意味着没有办法动态的确定虚函数覆写的是那个基类的虚函数;私有继承介于
没有阅读和模板有关的章节,将已经是常识的概念没有记录
使用
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-a和
has-a的关系之间。
相关文章推荐
- <<Effective c++>>读书笔记---条款20:宁以pass-by-reference-to-const替换pass-by-value
- <<Effective C++>>读书笔记4: 设计与声明
- <<More Effective C++>>读书笔记6: 杂项
- <<Effective c++>>读书笔记---条款19:设计class犹如设计type
- <<Effective C++>>读书笔记9: 杂项讨论
- <<Effective C++>>读书笔记(三)
- <<More Effective C++>>读书笔记2: 运算符
- <<More Effective C++>>读书笔记3: 异常
- <<Effective C++>>读书笔记(二)
- <<Effective C++>>读书笔记(1)
- <<More Effective C++>>读书笔记4: 效率
- <<Effective C++>>读书笔记8: 定制new和delete
- <<Effective C++>>读书笔记7: 模板与泛型编程
- <<Effective C++>>读书笔记3: 资源管理
- <<Effective C++>>读书笔记(一)
- <<More Effective C++>>读书笔记1: 基础议题
- <Effective C++>读书笔记-6
- <<Effective C++>>读书笔记5: 实现
- <Effective C++>读书笔记-1
- <Effective C++>读书笔记-3