第一章 关于对象
快速记录一些要点:
- {P6} 讲到C++相对于C多了封装,但这个封装大多数情况下并没有带来额外的布局成本,即并未带来任何空间或执行期的不良后果。C++在布局和存取时间上主要的额外负担是由virtual引起。 此外一些多重继承下也会发生一些负担。比如说:每个对象要有虚表指针,需要有thunk切换等等。
- {P9-P10} 一些对象模型历史和比较
- 简单对象模型:每个数据和函数都占据一个slot。 对于static和成员函数来说,没有必要浪费这么多空间
- 表格驱动模型:两个指针,一个指向所有数据的表,一个指向所有函数的表。多了一层间接,没有必要
- 现在主流使用的:vtbl 和 vptr 。优点:空间和存取时间的效率;缺点:成员有所修改,需要重编。
- {P21} C和C++原来struct代码混用
struct C_point {...};
class Point {
public:
operator C_point() { return _c_point;}
//...
private:
C_point _c_point;
}
- {P31-P34} 子类对象赋值给父类对象
class Base {... virtual void t(){}};
class D : Base {... void funcd(){}};
Base b;
D d;
Base b1 = d; //发生裁剪(切割)
发生了切割很容易理解,因为D的空间比Base大。
但问题来了: 这里对象中的vptr是Base的还是D的呢?
答案是 Base的 因为必须符合Base对象的基本语义。
反推:此时你获得是一个Base对象,大小也就Base这么大。假设是D的vptr,那么用到this的B之外的成员怎么办?
Base& b2 = d;
Base* b3 = &d;
对于以上的调用,并没有改变对象内容,只是对内容的描述(读取)方式不同。这种方式可以支持多态。
- 一个class object所需的内存,一般而言由以下部分组成:
- nonstatic data members的总和大小;
- 任何由于alignment需求而填补的大小;
- 为支持virtual而内部产生的额外负担。