立志要把D&E看两三遍,所以这边列一个读书笔记,觉得什么有必要就记下来.
1. 内联
在带类的C里面,在类声明里面实现的成员函数,可以被内联.
class stack { //会被内联 char pop() { if(top <= min) error("stack underflow"); return *--top; } };
在C++里面,提供的inline关键字,也可以用来内联.
另外,static修饰的非成员函数,有internal连接属性,也是可能会被内联掉.
2. 窄转换
早期想法不允许"破坏信息的"隐式转换.可是后来发现每个C程序内都有大量的int到char的转换.....
隐式的变窄转换,通常会给warning,除非显式的调用转换.除了int到char...
3. C++里面的保护概念(public/private/protected)
保护是通过编译时的机制提供,目标是防止发生意外事件,而不是防止欺骗或者有意的侵犯.
访问权由类本身授予,而不是单方面的取用.
访问权控制是通过名字实行的,而不依赖于被命名事物的种类.
保护的单位是类,而不是个别对象.
受控制的是访问权,而不是可见性.
4. 覆盖和虚函数匹配
class Base { public: virtual void f(); virtual void g(int); }; class Dervided : public Base { public: void f(); //overrides Base::f() void g(char); //doesn't override Base::g() };
非虚函数Dervided::g和Base::g没有任何关系,但是却覆盖了它.这很容易导致出错,编译器没有给任何警告.
5. 基类成员的遮蔽
派生类里面的名字将遮蔽基类中具有相同名字的任何对象货函数.
6. +=操作符
+=这一类操作符是更基本的,他们比常规算术的兄弟+等等的效率更高. 最好是先把+=, *=一类的赋值运算符函数定义成成员函数,然后把+,*一类定义成全局函数.
7. const的由来
C++之父说要有readonly,于是乎标准最后加进去const.但是这边的const,和readonly还是有一点差别,就是语言并没有任何机制去保证这个东西是readonly的.
还有,全局const变量具有internal链接属性.这是和优化有关的,标准作了假设,就是你不会修改这个const变量,所以不需要在其他单元内连接到同一个对象.
8. 临时变量的生命周期
临时变量,一定是某一个表达式的子表达式. 当临时变量不再是任何一个表达式的子表达式时,就可以被析构了.
术语叫,完整表达式的结束.
9. restrict指针
restrict指针是用来优化的,主要面向数值计算.如果无特殊需求,可以不用此关键字,否则两个指针的内容有叠加部分,可能会优化出错.
10. 细粒度的重载
重载会优先匹配准确的类型,匹配不上才会类型提升或者隐式转换.
另外, 'x'在C++里面是char,在C里面居然是int.
11. 重载的匹配规则
1) 匹配中不转化或者只是用不可避免的转换,比如,数组名到指针,函数名到函数指针,以及T到const T.
2) 使用整形类型提升的匹配,ANSI C里面定义的,char到int,short到int,以及他们对应的unsigned类型,以及float到double.
3) 使用标准转换匹配.例如int到double, dervied*到base*,unsigned int到int等.
4) 使用了用户定义转换的匹配. 包括构造函数以及转换操作符.
5) 使用了在函数声明里的省略号...的匹配
如果存在两个最高的匹配,就是有歧义,便会产生一个编译错误.
12. NonCopyable
简单的把复制构造函数和赋值函数都定义为私有.
13. 防止派生
析构函数私有...
其实C++11有final关键字,也可以用来放置派生
14. 按成员复制
对象复制被定义为对所有非晶态成员和基类成员的按成员复制.
如果指针成员按照默认拷贝构造函数和赋值函数复制,就应该给出warning.
15. 前置++,后置++操作符
class Ptr_to_x { X& operator++(); //前置 X operator(int); //后置 };
16. bool类型
bool是一个特别的整型类型,带有字面量true和false. 非零值可以隐式转化到true, true可以隐式转化到1; 零值可以隐式转化到false, false可以隐式转化到0.
15. 放松覆盖规则
函数的返回类型,不是需要严格匹配都可以覆盖.
class B{ public: virtual B* clone() { return new B(*this); } }; class D : public B{ public: virtual D* clone() { return new D(*this); } //放松返回类型 void h(); }; void gg(B* pb, D* pd) { B* pb1 = pb->clone(); D* pd1 = pd->clone(); pd->clone()->h(); D* pd2 = pb->clone(); //error pb->clone()->h(); //error }
16. protected关键字
Mark是Interviews的主设计师.他说服老爹在C++里面加入protected.有一万个理由支持这种观点.....
五年后,Mark在interviews里面禁止使用protected成员,因为他们已经变成许多程序错误的根源....泪奔
17. RTTI的正确使用
1) 最可取的是根本不用运行时类型信息机制,完全依靠静态类型检查
2) 如果搞不定, 使用动态转换.
3) 如果必要的话,使用typeid()做比较.
4) 如果确实需要知道一个类型的更多信息, 就需要用typeid相关的操作.