============================================================================
3-0. 类所占的内存大小受到三个因素的影响:
(1)语言本身所造成的额外负担(Virtual base classes);
(2)编译器对于特殊情况所提供的优化处理(空基类优化);
(3)Alignment的限制(对齐);
注:Empty Virtual base class提供一个Virtual interface,没有定义任何数据,某些编译器对此提供了特殊处理(优化):一个empty virtual base class被视为derived class object最开头的一部分,也就是说它并没有花费任何额外空间。

============================================================================

3-1. Data Member 的绑定
member rewriting rule:一个inline函数实体之内,在整个class 声明未被完全看见之前,是不会被评估求值的。也即:

extern int x;
class Point3d
{
public:
// 对于函数本身的分析将延迟直至class声明的右大括号出现才开始
float X() const { return x; }
private:
float x;
};
// 事实上,分析在这里进行

对member functions本身的分析,会直到整个class的声明都出现了才开始。因此,在一个inline member function躯体之内的一个data member 绑定操作,会在整个class声明完成之后才发生(这就保证取用到的变量是 data member 而不是 global )。

但是对于argument list(函数参数列),还是会在他们第一次遇到时被适当地决议完成。

============================================================================
3-2. Data Member 的布局
Nonstatic data members 的class object 中的排列顺序将和其被声明的顺序一样,任何中间介入的static data members 都不会被放进对象布局之中。

============================================================================

3-3. Data Member 的存取
(1)Static Data Members:被编译器提出于class之外,并被视为一个global变量(但只在class生命范围之内可见),其不会导致任何空间上或执行时间上的额外负担。每一个Static Data Members只有一个实体,存放在程序的data segment之中,每次程序取用static member,就会被内部转化为对该唯一的extern实体的直接取用操作。

(2)Nonstatic Data Members
Nonstatic Data Members:直接存放在每一个class object之中,除非经由明确的(explicit)或暗喻的(inplicit)class object,没有办法直接存取它们。只要程序员在一个member function中直接处理一个Nonstatic Data Members,所谓“implicit class object”(this指针)就会发生。
每一个Nonstatic Data Members的偏移量(offset)在编译时期即可获知,甚至member属于一个base class subobject(派生自单一或多重继承串链)也是一样。因此,存取一个Nonstatic Data Members,其效率和存取一个C struct member或一个nonderived class 的 member是一样的。

注:经由对象(object)和经由ptr取用成员x,如果成员member是从一个Virtual base class继承而来时,ptr存取操作会延迟至执行期。而经由object的取用操作,members的offset位置在编译时期就固定了。

============================================================================
3-4. “继承”与 Data Member
(1)只要继承不要多态

(2)加上多态

注:a. 单一继承提供了一种“自然多态”形式,是关于classes 体系中的base type 和 derived type之间的转换。base class 和 derived class 的objects都是从相同的地址开始,其间差异只在于 derived object 比较大,用以容纳它自己的nonstatic data members。
b. 当把vptr放在class object 的起始处,如果base class 没有virtual function 而derived class 有(如书 图3.2b),那么单一继承的自然多态就会被打破。在这种情况下,把一个derived object 转换为其base 类型,就需要编译器介入,用以调整地址(因vptr插入之故)。在既是多重继承又是虚拟继承的情况下,编译器的介入更有必要。

(3)多重继承

(4)虚拟继承

《深度探索C++对象模型》中介绍了3种实现模型。这里只说一下第3种:是在Virtual function table(虚函数表)中放置 Virtual base class 的offset(而不是地址),图3.5b 显示这种base class offset 实现模型。至此,Virtual function table 可经由正值或负值来索引。如果是正值,很显然就是索引到Virtual functions;如果是负值,则是索引到Virtual base class offset。
注:一般而言,Virtual base class 最有效的一种运用形式就是:一个抽象的Virtual base class ,没有任何data members。

============================================================================
3-6. 指向Data Members 的指针
详细调查class members 的底层布局,可用以决定vptr是放在class的起始处或是尾端。也可以用来决定class 中的access sections 的次序。
假设类有3个float成员,如果vptr放在对象的尾端,则3个成员的offset(& Class::object1)分别是0,4,8. 如果vptr放在对象的起头,则3个成员在对象布局中的offset分别是4,8,12. 然而你若去取data members的地址,传回的值总是多1. 也就是1,59或者5,9,13等等。之所以这样,原因如下:

多重继承下,情况会有所不同:

============================================================================

Inside The C++ Object Model(三)的更多相关文章

  1. C++学习书籍推荐《Inside the C++ Object Model》下载

    百度云及其他网盘下载地址:点我 作者简介 Stanley B. Lippman is Architect with the Visual C++ development team at Microso ...

  2. inside the C++ Object model总结

    一. 关于对象 1.内联函数:能够除去函数调用的开支,每一处内联函数的调用都是代码的复制.这是一种空间换取时间的做法,若函数代码量大或者有循环的情况下,不宜内联(这件事有些编译器会自动帮你做).在类中 ...

  3. 《深度探索C++对象模型(Inside The C++ Object Model )》学习笔记

    转载:http://dsqiu.iteye.com/blog/1669614 第一章 关于对象 使用class封装之后的布局成本: class并没有增加成本,data members直接内含在每一个c ...

  4. Inside The C++ Object Model - 03

    object Lessons 1.C++中布局以及存取时间上的的额外负担是由virtual引起的:virtual function.virtual base class.或是由于多继承引起的. 2.C ...

  5. Inside The C++ Object Model - 01

    前言 1.Foundation项目是一个定义大系统开发模型的项目,又叫Grail. 2.Grail中编译器被分为:parser(语法分析)->type checking -> simpli ...

  6. Inside The C++ Object Model(五)

    ============================================================================5-0. 一般而言,class 的data me ...

  7. Inside The C++ Object Model(四)

    ============================================================================4-1. Member 的各种调用方式静态成员函 ...

  8. Inside The C++ Object Model(二)

    ============================================================================2-0. 关键字explicit被引入C++,提 ...

  9. Inside The C++ Object Model(一)

    ============================================================================1-1. 关键字struct和class的一点区 ...

随机推荐

  1. windows安装并使用Anaconda

    前言 本意是要使用Jupyter(Jupyter官网地址),在Jupyter官网上看到,强烈建议新手使用Anaconda,于是开始下载Anaconda使用.Anaconda是用于管理开源包(packa ...

  2. C_汉诺塔的故事(递归)

    汉诺塔: 汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命令婆罗门把圆盘从下面开始按大小顺 ...

  3. C_关于递归算法的几个例子

    1.递归算法的定义: 2.递归与迭代的优劣 eg1:斐波那契数列:斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibona ...

  4. C#完美任意设置webBrowser框架默认的IE内核版本

    通常情况下,我们直接调用C#控件webBrowser1控件的时候 默认是IE7  用webBrowser1控件打开IE内核检测网站内容是这样滴 我们在程序里面写入以下代码 /// <summar ...

  5. 介绍三款串口监控工具:Device Monitoring Studio,portmon,Comspy

    在开发上位机下位机通讯程序时,有一个好的监控工具会事半功倍.特在网上找了几款串口监控软件,作了简单对比: 一.Device Monitoring Studio 网址:http://www.hhdsof ...

  6. Github超棒资源汇总

    Awesome List 中文资源大全 经典编程书籍大全 免费的编程中文书籍索引 awesome-awesomeness-zh_CN https://github.com/jnv/lists awes ...

  7. SpringBoot(十三):springboot2.0.2定时任务

    使用定义任务: 第一步:启用定时任务第二步:配置定时器资源等第三步:定义定时任务并指定触发规则 1)启动类启用定时任务 在springboot入口类上添加注解@EnableScheduling即可. ...

  8. 微信小程序登录逻辑

    wx.getStorage({ key: 'session_id', success: function(res) { //如果本地缓存中有session_id,则说明用户登陆过 console.lo ...

  9. mysql忘记密码时如何修改密码

    1.首先关闭mysql服务 2.进入mysql安装目录,我的是在C:\Program Files\MySQL\MySQL Server 5.5\bin 3.dos命令行执行:mysqld -nt -- ...

  10. 【原】Linux环境下Shell调用MySQL并实现定时任务

    对于一些周期性事务,我们可以在Linux下,使用shell脚本调用mysql数据库存储过程,并设置定时任务. 本来是要mysql数据库中创建事件任务来,定时执行存储过程,做数据传输的...使用cron ...