您的位置:首页 > 编程语言 > C语言/C++

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

2017-05-18 16:58 316 查看
谨以此书作为现代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-a
has-a
的关系之间。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: