




免费预览已结束,剩余17页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
编译器的设计与实现 -多态 制作: 张 云 时间:2008-04 加入多态 n目标: 在继承的基础上增加多态的支持。 n问题:什么是多态? 从字面上来理解,“多种形态”,即,同样的消息被不同 类型的对象接受时导致的完全不同的行为。 多态性是允许你将父对象设置成为和一个或更多的他的 子对象相等的技术,赋值之后,父对象就可以根据当前 赋值给它的子对象的特性以不同的方式运作(摘自 “delphi4 编程技术内幕”)。 多态性在c+中通过虚函数(virtual function)来实现 。 示例 class shape int a; virtual void draw() a=0; cout“shape”endl; class line : class shape void draw() a = 1; cout“line”endl; class circle : class shape void draw() a = 2; cout“circle”endl; void foo(shape s) s.draw(); /cout“a=”s.aendl; void main() shape s = new shape(); shape l= new line(); shape c = new circle(); foo(s); foo(l); foo(c); 示例 class shape int a; virtual void draw() a=0; cout“shape”endl; class line : class shape void draw() a = 1; cout“line”endl; class circle : class shape void draw() a = 2; cout“circle”endl; void foo(shape s) s.draw(); /cout“a=”s.aendl; void main() shape s = new shape(); shape l= new line(); shape c = new circle(); foo(s); foo(l); foo(c); 在foo()函数中,接收的参数时 shape类型的,在执行s.draw(); 语句的时候如何能够判断出来应 该调用哪一个类成员函数呢? 输出如下: “shape” “line” “circle” 支持多态需要的内容 1 虚函数应该如何运行? 2 如何实现? 3 对应的目标代码? void foo(shape s) s.draw(); /cout“a=”s.aendl; void main() shape s = new shape(); shape l= new line(); shape c = new circle(); foo(s); foo(l); foo(c); 虚函数应该如何运行 输出: “shape” “line” “circle” 调用shape:draw(); 调用line:draw(); 调用circle:draw(); 在main()中记录了不同的对象的不同类型 ;但是,关键在于在foo函数中,它接收的 参数类型是shape,它是如何判断出来每 一个传入参数对象的不同类型的? 虚函数应该如何运行 void foo(shape s) s.draw();/ ?_draw(s) n问题的关键在于:在main()函数中虽 然可以保留不同的参数对象的信息; 但是在foo()函数中,接收的参数是 shape类型的,在执行s.draw();语句 的时候如何能够判断出来应该调用哪 一个类成员函数呢?(回想一下以前 学过的知识,能解决找个问题吗?注 意:子类对象可以很容易的被“裁减 ”成父类对象!) foo proc near mov ax, bp-1 push ax call ?_draw; ret 运行的 时候才 能确定 问题? n多态性体现在允许将子类类型的指针赋值给父 类类型的指针,但是仍旧调用子类定义的操作 。(与继承的比较) n也就是说,父类指针可以指向不同的子类对象 ;根据指向对象的真正类型的不同调用不同的 操作。而只能在运行的时候才能去判断到底该 指针指向的对象的类型。(思考:为什么编译 的时候不能判断出来?) n问题:如何在运行时判定当前对象的指针所指 的对象类型? 解决 n关键字virtual 表示与普通成员函数的 不同 nvitual table 记录类中所有虚函数的入 口地址;根据函数地址调用正确的函数 nvpointer(vptr) 指向虚函数表,从而 可以在运行的时候查找虚函数代码的地 址。在给类对象分配空间的时候需要分 配这样一个指针的空间大小,用来存放 虚指针 关键字virtual class shape int a; virtual void draw() a=0; cout“shape”endl; class line : class shape void draw() a = 1; cout“line”endl; class circle : class shape void draw() a = 2; cout“circle”endl; 表明该类及其继 承类中的draw() 函数是虚函数! virtual table / ?_draw(s) foo proc near mov ax, bp-1 push ax ;传递this指针 /通过查找vtable得到需要 调用函数的入口地址 /call _v_draw ; mov ax, ax mov ax, ax call ax ret shape中的draw()为虚函数 且偏移为0(表示是第一个 虚函数) 执行s.draw()时,通过this 指针找到vptr,然后找到 vptr所指向虚表的第一个 元素的内容,即第一个虚 函数的入口地址 /虚拟机运行的时候需要做的修改 /vcall near ptr _v_xx /查找正确的虚函数表,设置pc值; void vcall(string arg) this.stackcpu.sp = cpu.bp; cpu.bp = cpu.sp; this.stackcpu.bp+1=cpu.pc; cpu.sp+=2; /从metadatafield以及虚函数表中取得函数的入口地址 string clsname=null;string funname=null; 从参数arg中获取类型名和函数名 int rva; 从符号表中获取当前虚函数的偏移量 rva = vf.rva; /获取所调用函数的目标代码的开始位置 int vfaddr = heapcpu.thisp+convert.toint16(rva);
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年机场航空运营专家考试试题及答案解析
- 机电维修基础知识培训
- 2025年物流仓储安全操作题库
- 2025年安全生产保障题及答案
- 希沃课件制作教学设计
- 2025年建筑施工安全培训题及答案
- 2025年安全管理实操题及答案指南
- 2025年大数据技术应用能力提升专项面试模拟题及参考答案
- 2025年数据分析师职业技能水平评价试题
- 2025年健康指导员笔试模拟试卷
- 2024年杭州市公务员考试行测真题及完整答案详解一套
- 2025 八项规定应知应会100题题库及参考答案详解(综合题)
- 单位保安执勤方案(3篇)
- 2025年安徽省普通高中学业水平选择性考试(思想政治)科目高考真题+(答案解析版)
- 2025年陕西省单招试题及答案
- 2025年陕西省中考地理试题(含标准答案)
- x酒店项目可行性项目可行性研究报告
- 陕西建筑资质管理办法
- 宝钢质量一贯制管理办法
- 2025年《治安管理处罚法》新修订课件
- 金属非金属地下矿山六大系统建设规范
评论
0/150
提交评论