现在的位置: 首页 > 综合 > 正文

深入探索C++对象模型 第一章 关于对象

2017年12月25日 ⁄ 综合 ⁄ 共 2207字 ⁄ 字号 评论关闭
1、为了实现兼容性,在C++中,struct==class,两个关键字对于编译器来说在大部分的地方是完全一样的可以互相的替代(在template的定义中有个定义,类似于 template<class Type>,因为模板并没有打算兼容C,所以这里的class并不能用struct,也许是为了避免这种矛盾,所以后来用typename来替代了class
),因此当你看到这样的声明: class node; 而见到了这样的定义 struct node{...};这两个其实说的是一个类,不用担心任何的错误
2.对象模型主要有:简单对象模型和表格对象模型
简单对象模型:对象中的成员是以slot的索引值来寻址,找到对应的成员
表格对象模型:将数据成员和成员函数分别放置在2个表格中,对象本身只包含指向2个表格的指针
3.现在的C++对象模型主要是:对象包含所有的非静态数据成员,除此之外的其他包括静态数据,静态和非静态成员函数都是存放在对象之外的。
对象访问虚函数:a.每一个类产生一堆指向虚函数的指针,放在表格中,这个表格被称为虚函数列表
                            b.每一个对象被安插一个指针,指向相关的虚函数列表,虚函数表中第一个表示对象的类型信息,然后依次表示对象的虚函数
4.在虚拟继承的情况下,base class不管在继承串链中被派生(derived)多少次,永远只会存在一个实体(称为subobject).一个继承类如何实现其基类模型,可以通过类似于表格对象模型实现
一个derived class如何在本质上模塑其base class的实体呢?在"简单对象模型"中,每一个base class可以被derived class object内的一个slot指出,该slot内含base class subobject的地址.这个机制的主要缺点是,因为间接性而导致空间和存取时间上的额外负担,优点则是class object的大小不会因其base
classes的改变而受到影响.
当然也可以想像另一种所谓的base table模型.这里所说的base class table被产生出来时,表格的每一个slot内含一个相关的base class地址,这很像virtual table内含每一个virtual function的地址一样.每一个class object内含一个bptr,它会被初始化,指向其base class table.这种策略的主要缺点是由于间接性而导致的空间和存取时间上的额外负担,优点则是在每一个class
object中对于继承都有一致的表现方式:每一个class object都应该在某个固定位置上安放一个base table的指针,与base classes的大小或数目无关.第二个优点是,不需要改变class object本身,就可以放大,缩小或更改base class table.
C++最初采用的继承模型不运用任何间接性:base class subobject 的 data members被直接放置于derived class object中.这提供了对base class members最紧凑而且最有效率的存取.缺点就是:base class members的任何改变,包括

增加,移除或改变类型等等,都使得所有用到"此 base class或其 derived class之objects"者必须重新编译.
自C++2.0才新导入的virtual base class,需要一些间接的base class表现方法.Virtual base class的原始模型是class object中为每一个有关联的virtual base class加上一个指针.其他演化出来的模型则若不是导入一个virtual

base class table.就是扩充原已存在的virtual table.以便维护每一个virtual base class的位置
5.C++中的多态智能存在于public class体系中
6.一个对象的大小:其非静态数据成员的总和大小+支持虚函数指针,一个指针的大小是固定的,不管指针指向的是什么数据类型,指针类型会教导编译器如何解释某个特定地址的内存内容及其大小
7.为什么多态只能由指针或者引用来触发,比如如下的定义

                B b;   A a=b; a.fn();


               这种情况下的过程是这样的。


               步骤一、构建b对象的内存分布。


               步骤二、用b对象的内存分布来初始化a,因为b对象的内存分布本身就建立在a内存分布之上的,所以可以初始化,但是是一种切割掉的初始化。而关于vptr的刷新,C++的标准规定:编译器必须确保如果某个object含有一个或一个以上的vptrs,那些vptrs的内容不会被刷新(如上的猜想就是基于这个规定),因此由于此时a的vptrs没有被刷新(b中有两个vptrs),所以当调用的时候就是调用的a中的实现。

8.类继承中对象的大小包含父类对象的大小+子类中非静态数据成员的大小+指向虚函数列表指针的大小,子类继承中,对象包含了父类的成员+自身的成员+虚函数列表,其虚函数列表中是子类改写父类的虚函数的成员函数地址和没有改写的父类的虚函数地址。
9.有虚函数的类的对象都有虚函数列表,列表为类似数组,数组中的对象为指向各个虚函数的指针(第一个指向自身对象的信息,从第二个开始依次指向虚函数)

抱歉!评论已关闭.