免费预览已结束,剩余1页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C+类对象创建过程揭密分类:Linux开发c/c+2007-08-04 08:18654人阅读评论(1)收藏举报介绍初 看到这个题目,你可能会有些疑惑:C+类对象的创建还有什么好说的,不就是调用构造函数么?实际上情况并不是想象中的那么简单,大量的细节被隐藏或者被 忽略了,而这些细节又是解决一些其他问题的关键,所以我们很有必要深入到这块神秘的区域,去探索鲜为人知的秘密。分配空间(Allocation)创建C+类对象的第一步就是为其分配内存空间。对于全局对象,静态对象以及分配在栈区域内的对象,对它们的内存分配是在编译阶段就完成了,而对于分配在堆区域内的对象,它们的分配是在运行是动态进行的。内存空间的分配过程涉及到两个关键的问题: 需要分配空间的大小,即类对象的大小。这么问题对于编译器来说并不是什么问题,因为类对象的大小就是由它决定的,对于要分配多少内存,它最清楚不过了。 是否有足够的内存空间来满足分配。对于不同的情况我们需要具体问题具体分析:o 全局对象和静态对象。编译器会为他们划分一个独立的段(全局段)为他们分配足够的空间,一般不会涉及到内存空间不够的问题。o 分配在栈区域的对象。栈区域的大小由编译器的设置决定,不管具体的设置怎样,总归它是有一个具体的值,所以栈空间是有限的,在栈区域内同时分配大量的对象会导致栈区域溢出,由于栈区域的分配是在编译阶段完成的,所以在栈区域溢出的时候会抛出编译阶段的异常。o 分配在堆区域的对象。堆内存空间的分配是在运行是进行的,由于堆空间也是有限的,在栈区域内试图同时分配大量的对象会导致导致分配失败,通常情况会抛出运行时异常或者返回一个没有意义的值(通常是0)。初始化(Initialization)这 一阶段是对象创建过程中最神秘的一个阶段,也是最容易被忽视的一个阶段。要想知道这一阶段具体完成那些任务,关键是要区分两个容易混淆的概念:初始化 (Initialization)和赋值(Assignment)。初始化早于赋值,它是随着对象的诞生一起进行的。而赋值是在对象诞生以后又给予它一个 新的值。这里我想到了一个很好的例子:任何一个在医院诞生的婴儿,在它诞生的同时医院会给它一个标识,以防止和其他的婴儿混淆,这个标识通常是婴儿母亲所 在床铺的编号,医院给婴儿一个标识的过程可以看作是初始化。当然当婴儿的父母拿到他们会为他们起个名字,起名字的过程就可以看作是赋值。经过初始化和赋值 后,其他人就可以通过名字来标识他们的身份了。区分了这两个概念后,我们再转到对对象初始化的分析上。对类对象的初始化,实际上是对类对象内的所有数据成 员进行初始化。C+已经为我们提供了对类对象进行初始化的能力,我们可以通过实现构造函数的初始化列表(member initialization list)来实现。具体的情况是否是这样的呢?下面我们就看看具体的情况是什么样的吧。我写了两个简单的类:classCInnerClasspublic:CInnerClass(intid):m_iID(id)CInnerClass&operator=(constCInnerClass&rb)m_iID=rb.m_iID;return*this;private:intm_iID;classCJdBasepublic:CJdBase:CJdBase(intid):m_innerObj(id),m_iID(id)m_innerObj=10;private:CInnerClassm_innerObj;intm_iID;我们重点是看看CJdBase类的构造函数。CJdBase类的构造函数提供了初始化列表,用来初始化其成员变量,其相应的汇编代码如下(注:我只保留了关键的代码):movDWORDPTR_this$ebp,ecxmoveax,DWORDPTR_id$ebppusheaxmovecx,DWORDPTR_this$ebpcall?0CInnerClassQAEHZ;CInnerClass:CInnerClassmoveax,DWORDPTR_this$ebpmovecx,DWORDPTR_id$ebpmovDWORDPTReax+4,ecx;5:m_innerObj=10;push10;0000000aHleaecx,DWORDPTR$T1359ebpcall?0CInnerClassQAEHZ;CInnerClass:CInnerClassleaeax,DWORDPTR$T1359ebppusheaxmovecx,DWORDPTR_this$ebpcall?4CInnerClassQAEAAV0ABV0Z;CInnerClass:operator=从这段汇编代码中我们可以看到一些有意义的内容: 初始化列表先于构造函数体内的代码执行; 初始化列表确实执行的是数据成员的初始化过程,这个可以从成员对象的构造函数被调用看的出来。赋值(Assignment)对 象经过初始化以后,我们仍然可以对其进行赋值。和类对象的初始化一样,类对象的赋值实际上是对类对象内的所有数据成员进行赋值。C+也已经为我们提供了 这样的能力,我们可以通过构造函数的实现体(即构造函数中由包裹的部分)来实现。这一点也可以从上面的汇编代码中成员对象的赋值操作符 (operator =)被调用得到印证。结束随着构造函数执行完最后一行代码,可以说类对象的创建过程也就顺利完成了。由以上的分析可以看出,构造函数实现了对象的初始化和赋值两个过程:对象的初始化是通过初始化列表来完成,而对象的赋值则才是通过构造函数,或者更准确的说应该是构造函数的实现体。虚函数表指针(VTable Pointer)我 们怎么可能会忽视虚函数表指针呢?如果没有它的话,C+世界会清净很多。我们最关心的是对于那些拥有虚函数的类,它们的类对象中的虚函数表指针是什么时 候赋值的?我们没有任何代码,也没有任何能力(当然暴力破解的方法除外)能够在类对象创建的时候给其虚表指针赋值,给虚表指针赋值是编译器偷偷完成的,具 体的时机是在进入到虚函数后,在给对象的数据成员初始化和赋值之前,编译器偷偷的给虚表指针赋值。下面我们就看看具体的情况是什么样的吧。在上面的 CJdBase类的基础上再添加一个虚函数:classCJdBasepublic:CJdBase:CJdBase(intid):m_innerObj(id),m_iID(id)m_innerObj=10;public:virtualvoiddumpMe()private:CInnerClassm_innerObj;intm_iID;使用VS2002编译获得这个构造函数的汇编代码,其中最关键的一些代码如下:movDWORDPTR_this$ebp,ecxmoveax,DWORDPTR_this$ebpmovDWORDPTReax,OFFSETFLAT:?_7CJdBase6Bmoveax,DWORDPTR_id$ebppusheaxmovecx,DWORDPTR_this$ebpaddecx,4call?0CInnerClassQAEHZ;CInnerClass:CInnerClassmoveax,DWORDPTR_this$ebpmovecx,DWORDPTR_id$ebpmovDWORDPTReax+8,ecx;5:m_innerObj=10;push10;0000000aHleaecx,DWORDPTR$T1368ebpcall?0CInnerClassQAEHZ;CInnerClass:CInnerClassleaeax,DWORDPTR$T1368ebppusheaxmovecx,DWORDPTR_this$ebpaddecx,4call?4CInnerClassQAEAAV0ABV0Z;CInnerClass:operator=从这些代码中的movDWORDPTReax,OFFSETFLAT:?_7CJdBase6B我们可以清晰的看到,在构造函数的最开始,在进入构造函数体内部,甚至是在进入初始化列表之前,编译器会插入代码用当前正在被构造的类的虚表地址给虚表指针赋值。后记如果不是亲自实践和分析,很难想象一个简单的类对象创建过程竟然蕴涵了这么多秘密。了解了这些秘密为我们解决其他的一些问题打开了胜利之门。试试下面的一些问题,不知道在你看完本文后是否能够有一种豁然开朗的感觉:
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 中年职工心理健康关怀方案
- 医养结合大楼建筑防水与防潮设计方案
- 财务部门月度报表编制与审核流程
- 环境监测系统建设与应用方案
- 2026年张家口职业技术学院单招职业倾向性测试必刷测试卷新版
- 2026年安阳职业技术学院单招综合素质考试必刷测试卷及答案1套
- 2026年山西老区职业技术学院单招职业适应性考试必刷测试卷及答案1套
- 养牛场粪污处理与利用系统
- 2026年福建华南女子职业学院单招职业适应性测试必刷测试卷附答案
- 电力线路建设质量控制措施
- 2025年高考地理山东卷试卷评析及备考策略(课件)
- 公交司机消防安全培训课件
- 2024年石河子大学公开招聘辅导员笔试题含答案
- 非法采矿案例课件
- 12345政务热线培训
- 高速公路收费员招聘考试试题及答案
- 2025煤矿安全规程解读
- 建筑行业施工安全管理制度汇编
- 消控室安全知识培训课件
- 个人劳动防护用品的使用和维护安全培训
- 保密知识培训提纲课件
评论
0/150
提交评论