条款09:不要在构造函数或析构函数中调用虚函数
子类构造过程中先初始化基类,子类还没有构造完成,只会调用基类的虚函数。一种通俗说法更好,此时的虚函数还不是虚函数。
解决办法:由下向上传递,将派生类构造函数时,必要信息传给基类构造函数,由基类构造函数调用基类成员打印子类的信息。
条款22:将成员变量声明为private
这就是封装的好处:
一个public变量被取消,所有使用它的代码被破坏;
一个protect变量被取消,所有使用它的派生类代码被破坏;
一个private变量被取消,只有本类代码被破坏;
条款30:透测了解inlining的里里外外
观点:将对函数的每一个调用都用函数本体替换之(大部分编译器在编译期inline,部分编译器在链接期,最后少部分竟在运行期)。
可以避免一些因为函数调用所带来的开销。缺点:a但是会增大目标码的大小。在有内存限制的计算机上,inlining导致的代码膨胀会导致额外的换页行为,降低指令高速缓存器的击中率,以及伴随的效率损失。b inline无法随着程序库的升级而升级,f()为inline,客户将f本体安插如自己代码中,一旦f改变,所有客户代码必须重新编译。f不为inline,只需将修改的f编译,重新链接所有文件即可。这也是动态链接库技术的好处。
关于模板函数的inline,模板在使用时被具体化,inline在使用时替换之,但是模板的具体化和inline无关。
编译器拒绝太过复杂的调用(循环或递归),也会拒绝虚函数(直到运行时才确定调用哪个函数,而inline是在运行前替换成函数本体)。同时编译器也会拒绝函数指针的inline
所以inline只是对编译器的一个申请,编译器可以拒绝,大多数编译器如果无法将你的要求inline,会给出警告。
一个程序将80%的程序执行时间花费在20%的代码上,你要优化就必须找到这20%,并将之inline或瘦身。
条款31:将文件间的编译依存关系降至最低。
接口与 实现分离。编译依存最小化的本质:用“声明的依存性(前置声明)”替换“定义的依存性(#include"头文件")”。具体的做法是:在类A的头文件中使用类B的前置声明,在类A的实现文件中#include两个文件的头文件。
类内部数据成员如果是其他类对象,最好用引用或指针+前置声明,不要用对象本身(否则其他类修改,自己就要重新编译);
程序库的头文件应该以“完全且仅有声明式”。相依于声明式,不相依于定义式。
区分handle class和interface class(C++primer第五版的字符统计程序便是最好的例子)