- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
解析动态联编
多态性是C++最主要的特征,多态性的实现得益于C++中的动态联编技术。文章通过对动态联编的关键技术虚拟函数表进行深入的剖析,解析的动态联编的过程极其技术要领。 关键字 多态性 动态联编 VTABLE 虚函数 文章正文 一 从多态性谈动态联编的必要性在进入主题之前先介绍一下联编的概念。联编就是将模块或者函数合并在一起生成可 执行代码的处理过程,同时对每个模块或者函数调用分配内存地址,并且对外部访问也分配正确的内存地址。按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编和动态联编。在编译阶段就将函数实现和函数调用关联起来称之为静态联编,静态联编在编译阶段就必须了解所有的函数或模块执行所需要检测的信息,它对函数的选择是基于指向对象的指针(或者引用)的类型。反之在程序执行的时候才进行这种关联称之为动态联编,动态联编对成员函数的选择不是基于指针或者引用,而是基于对象类型,不同的对象类型将做出不同的编译结果。C语言中,所有的联编都是静态联编。C++中一般情况下联编也是静态联编,但是一旦涉及到多态性和虚函数就必须使用动态联编。 多态性是面向对象的核心,它的最主要的思想就是可以采用多种形式的能力,通过一个用户名字或者用户接口完成不同的实现。通常多态性被简单的描述为一个接口,多个实现。在C++里面具体的表现为通过基类指针访问派生类的函数和方法。 下面我们看一个静态联编的例子,这种静态联编导致了我们不希望的结果。
//1.cpp
1. #include iostream.h
2. class shape{
3.?? public:
4.???? void draw(){coutI am shapeendl;}
5.???? void fun(){draw();}
6. };
7. class circle:public shape{
8.?? public:
9.???? void draw(){coutI am circleendl;}
10. };
11. main(){
12.???? class circle?? oneshape;
13.???? oneshape.fun();
14. }
程序的输出结果我们希望是I am circle,但事实上却输出了I am shape的结果,造成这个结果的原因是静态联编。静态联编需要在编译时候就确定函数的实现,但事实上编译器在仅仅知道shape的地址时候无法获取正确的调用函数,它所知道的仅是shape::draw(),最终结果只能是draw操作束缚到shape类上。产生I am shape的结果就不足为奇了。为了能够引起动态联编,我们只需要将需要动态联编的函数声明为虚函数即可。动态联编只对虚函数起作用。我们在通过基类而且只有通过基类访问派生类的时候,只要这个基类中直接的或者间接(从上上层继承)的包含虚函数,动态联编将自动唤醒。下面我们将上面的程序稍微改一下。
//2.cpp
1. #include iostream.h
2. class shape{
3.?? public:
4.????virtual void draw(){coutI am shapeendl;}
5.???? void fun(){draw();}
6. };
7. class circle:public shape{
8.?? public:
9.???? void draw(){coutI am circleendl;}
10. };
11. main(){
12.???? class circle?? oneshape;
13.???? fun(oneshape);
14. }
程序执行得到了正确的结果I am circle。代码在VC6.0中执行。 到目前为止我们不清楚动态联编的执行机制,但我们可以做个猜测。正如上面所说,对于函数的实际的对象类型不同,联编结果也应该不同。在静态联编中,执行的困难在于无法通过基类知道需要联编的子对象的确切类型。在1.cpp中shape的派生类既可能是circle,也可能是其余的rectangle或者square等等,到底应该静态联编哪一个呢。迷惑正在于此。动态联编在编译的时候应该也是不知道联编的确切对象类型的,(如果知道的话就成了静态联编了),因此它只能通过一定的机制,使得在执行时候能够找到和调用正确的函数体。可以想象,为了达到这个目的,一些相关信息应该封装在对象自身中。这些信息有点象身份证明,标识自己,这样在动态联编的时候,编译器可以根据这些标记找到相应的函数体,不要跑,就是你了。 实际上的动态联编过程是什么样的呢。二 对象类型信息为了证明我们的猜想,我们用下面的一个程序进行测试,下面的程序将获取普通的类和包含虚函数的类的字节大小。
您可能关注的文档
最近下载
- 科学主题班会.pptx VIP
- 植筋后锚固抗拔承载力现场检测作业指导说明书.doc VIP
- 2025武汉市简单房屋租赁合同.docx VIP
- 《帕金森病诊治》课件.ppt VIP
- 民法典全文内容.pdf VIP
- Starter知识点清单(含默写)2024-2025学年牛津上海版英语六年级上册.docx VIP
- 主题学习-探索中国的二十四节气课件-2024--2025学年初中地理商务星球版七上-.pptx VIP
- 民法典全文完整版跟民法典全文完整版婚姻概述.docx VIP
- (新浙教版)数学七年级上册培优讲义(共15讲).docx
- 2025年“中央八项规定“学习知识竞赛测试题库及答案.docx VIP
文档评论(0)