effective c++ 读书笔记
1、const char* const authorname = "Scott"
2、无法用define创建一个class专属常量,因为define并不重视作用域。一量定义 ,它就在其后的编译过程 中都有效
3、对于单存常量,最好以const对象或enum替换 define (宏使用的名称未进入记号表)
对于形似函数的宏,最好改用inline函数替换define
参数如果不需要更改,定义为const
4、const成员函数。const成员函数才可被const对象调用
5、bitwise constness (又称physical constness):不更改对象之任何成员变量(static除外)
和logical constness:一个const成员函数可以修改它所处理的对象内某些bits,但只有在客户端侦测不出的情况下才得如此。
mutable(可变的)释放掉non-static成员变量的bitwise constness约束。
编译器强制实施 bitwise constness,但你编写程序时应该使用logical constness
6、初始化:
为内置型对象 进行手工初始化,因为c++不保证初始化他们
构造函数最好使用成员初始列,而不是在构造函数中使用赋值操作。因为使用成员 初始列,会直接调用成员的构造函数。而使用赋值操作,赋值之前会先调用默认构造函数。
为免除“跨编译单元之初始化次序”问题,请以local staic 对象替换 non-local staic对象。
7、set_terminate
A terminate handler function is a function automatically called when the exception handling process has to be abandoned for some reason. This happens when a handler cannot be found for a thrown exception, or for some other exceptional circumstance that makes impossible to continue the handling process.
8、析构函数不要抛出异常。因为一: 在stack-unwinding过程中,会逆序调用对象有析构函数。此时会导致程序异常
二:确保析构函数总能完成 我们希望它做的所有 事情。
9、RAII:Resource Acquisition Is Initialization 。资源取得时机便是初始化时机,即资源在构造期间获得,在析构期间释放。
10、禁止复制
class Uncopyable{
protected:
Uncopyable(){} //允许derived 对象构造和析构
~Uncopyable(){}
private:
Uncopyable(const Uncopyable&); //但阻止copying
Uncopyable& operator=(const Uncopyable&);
};
只要任何人--甚至是member函数或friend函数--尝试拷贝对象,编译器便试着生成一个copy构造函数和一个copy assignment操作作符,这些函数的编译器生成版本会尝试调用其baseclass的对应兄弟。会被编译器拒绝,因为它们是private
11、资源管理器
class Lock{
public:
explicit Lock(Mutex* pm)
:mutexPtr(pm, unlock)
{
lock(mutexPtr.get());
}
private:
std::tr1::shared_ptr<Mutex> mutexPtr;
};
12、封装:它使我们能够改变事物而只影响有限客户
13、std是个特殊的名字空间,其管理规则也比较特殊。客户可以 全特化std内的templates,但不可以添加 新的templates(或classes或functions或其他 任何东西)到std里头。std的内容完全由c++标准委员会决定
14、Koenig Name Lookup: 查找当前命名空间中是否有匹配的函数声明. 如果函数中有类类型的参数, 那么这个类参数所在的命名空间也会被考虑到函数查找的范围内. 而且这两部分命名空间并没有先后顺序.
15、接口与实现分离
16、缺省参数值是静态绑定。而virtual函数是动态绑定。所以,有可能会在“调用一个定义于derived class 内的virtual函数”的同时,动使用 base class 为它所指定的缺省参数值。
17、复合:
复合(composition)是类型之间的一种关系 ,当某种类型的对象内含它种类型的对象,便是这种关系 。
public继承带有 is-a(是一种)的意义,复合也有它自己的意义。实际上它有两个意义。复合意味has-a(有一个)或is-implemented-in-terms-of(根据某物实现出)。那是因为你正打算在你的软件中处理两个不同的领域(domains)。程序中的对象其实相当于你所塑造的世界中的某些事物,这样的对象属于应用域(application domain)部分。其它对象则纯粹是实现细节上的人工制品,像是缓冲区、互斥器等等。这些相当于你软件中的实现域(implementation domain)。当复合发生于应用域内的对象之间,表现出has-a关系;当它发生于实现域内则是表现出is-implemented-in-terms-of的关系 。
private继承意味is-implemented-in-terms-of。这个跟复合一样。通常情况下,复合比较容易理解的。
18、static变量会自动初始化为全部是0
19、多重继承时,public继承某接口,private继承某实现
20、使用关键字typename标识嵌套从属类型名称,但不得在base class lists或member initialization (成员初始列)内以它作为base class修饰符。
21、可在derived class templates内通过 “this->"指涉 base class templates 内的成员 名称,或藉由一个明白写出的"base class资格修饰符”完成。
22、当我们编写一个class template,而它所提供 之“与此template相关的”函数 支持“所有参数之隐式类型转换”时,请将那些函数定义为"class template内部的friend函数“。条款46
23、Traint classes 使用”类型相关信息“在编译期可用。它们以templates和templates特化完成实现。
整合重载技术 后,traints classes有可能在编译期对类型执行 is...else测试。
24 template元编程(TMP,模板元编程)是编写templated-based c++程序并执行于编译期的过程 。即,以c++写成,执行于c++编译器内的程序。
25、static_cast < type-id > ( expression_r_r )
该运算符把expression_r_r转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
把空指针转换成目标类型的空指针。
把任何类型的表达式转换成void类型。
dynamic_cast
用法:dynamic_cast < type-id > ( expression_r_r )
该运算符把expression_r_r转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;如果type-id是类指针类型,那么expression_r_r也必须是一个指针,如果type-id是一个引用,那么expression_r_r也必须是一个引用。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
当dynamic_cast失败的时候,返回一个NULL指针
reinpreter_cast
它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。
该运算符的用法比较多。