这一章讲的东西很杂、所以我只归纳并延伸了一下标题提到的东西。比如这篇写一下纯虚函数和聚合类的构造。
一、纯虚函数:
1.含有纯虚函数的类不能有实例,所以一般纯虚函数没有定义。但是纯虚还是是可以加上定义并且也能够被调用的,但是必须满足以下条件(结合了C++Primer的知识点)
①纯虚函数的定义必须在类外。
②纯虚函数的调用必须是静态调用。即使用作用域限定符::,而不是使用 ‘->‘ 或 ‘.‘调用符。最简单的例子就是纯虚的析构函数,因为派生类的析构函数会被编译器器扩张以调用每一个上层的析构函数,所以需要抽象类定义纯虚析构函数。
class vBase { public: virtual void test()=0; void foo(); } void vBase::test() { } void vBase::foo() { vBase::test(); }
2.《深度探索C++对象模型》中,因为如果基类中有纯虚析构函数,则必须定义它,所以不建议将虚构函数设为纯虚。而在《effective C++》中,如果没有其余纯虚函数而编码者却希望构建一个抽象类,则可以将析构函数构造为纯虚函数。两者并不互斥。
二、聚合类
书中5.1讲了无继承情况下的对象构造,在讨论如何给成员变量设定初值时,讲了一个explicit initialization list要比构造函数的内联扩张(inline expansion)效率更高。其实这个所谓的显式初始化列表就是聚合类的列表初始化。
1.聚合类:①所有成员都是public。②没有定义任何构造函数。③没有类内初始值。④没有基类也没有虚函数
2.初始值列表:提供一个花括号括起来的成员初始值列表,初始值的顺序必须和声明顺序一致
struct Data { int ival; string s; }
void foo()
{ Data val={0,"string"};
}
3.效率:当函数的activation record被放进程序堆栈时,初始化列表中的常量就可以被放进val的内存中了。至于这个activation record则是堆栈框架(stack frame)的另外一个名称。在调用函数的时候被添加到调用栈,在函数返回的时候移除。它通常包含:被调用函数的地址,函数对调用者的返回地址,被调用函数的参数,先前的栈指针值。参考*上面对他的解释:What is activation record in the context of C and C++? - Stack Overflow
总结:就是聚合类的初始化列表效率比写一个构造函数,然后让编译器对构造函数进行扩展的效率要高。