版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第十五回:继承本质论发布日期:2007.9.10 作者:Anytao2007,作品,请注明作者和出处。本文将介绍以下内容:继承?继承的实现本质1.引言关于继承,你是否驾熟就轻,关于继承,你是否了如指掌。继承的基本概念,回归本质,从编译器运行的角度来揭示.NET 继承中的运本文不行本源,来发现子类对象是如何实现了对父类成员与方法的继承,以最为简陋的示例来揭示继承的实质,阐述继承机制是如何被执行的,这对于更好的理解继承,是必要且必然的。2. 分析下面首先以一个简单的动物继承体系为例,来进行说明:public abstract class Animalpublic abstract void Sho
2、wType(); public void Eat()Console.Wriine(Animal always eat.);public class Bird: AnimalaVXOGZK YZXOTM Z_VK # (OXJ !VHROI UKXXOJK UOJ 9NU:_VK a)UTYURK =XOOTK :_VK OY a c Z_VK !cVXOGZK YZXOTM IURUX!VHROI YZXOTM )URUXaMKZ a XKZXT IURUX! cYKZ a IURUX # GRK! cccVHROI IRGYY )NOIQKT (OXJaVXOGZK YZXOTM Z_VK
3、# )NOIQKT !VHROI UKXXOJK UOJ 9NU:_VK a)UTYURK =XOOTK :_VK OY a c Z_VK !cVHROI UOJ 9NU)URUX a)UTYURK =XOOTK )URUX OY a c )URUX !然后,在测试类中创建各个类对象,由于 Animal 为抽象类,cken 对象。只创建 Bird 对象和 Chi下面从编译角度对这一简单的继承示例进行深入分析,从而了解.NET强调的继承机制。是如何实现(1)简要的分析一下对象的创建过程:Bird bird 创建的是一个 Bird 类型的,而 new Bird()完成的是创建 Bird 对象,分配
4、内存空间和初始化操作,然后将这个对象赋给 bird象的关联。,也就是建立 bird与 Bird 对(2)从继承的角度来分析在编译器编译期是如何执行对象的创建过程,因为继承的本质就体现于对象的创建过程。在此以Chicken 对象的创建为例,首先是字段,对象一经创建,会首先找到其父类 Bird,并为其字段分配空间,而 Bird 也会继续找到其父类 Animal,为其分配空间,依次类推直到递归结束,也就是完成 System.Object 内存分配为止。可以在编译器中单步执行的方法来大致了解其分配的过程和顺序,因此,对象的创建过程是按照顺序完成了对整个父类及其本身字段的内存创建,并且字段的顺序是由上到
5、下排列,object 类的(OXJ GTOSGR # TK (OXJ !VHROI IRGYY :KYZ/TNKXOZGTIKaVHROI YOI UOJ 3GOT a(OXJ HOXJ # TK (OXJ !)NOIQKT INOIQKT # TK )NOIQKT !cccc字段排在最前面,其原因是如果父类和子类出现了同名字段,则在子类对象创建时,编译器会自动认为这是两个不同的字段而加以区别。然后,是方法表的创建,必须明确的一点是方法表的创建是类第一次加载到 CLR 时完成的,在对象创建时只是将其附加成员 TypeHandle 指向方法列表在 Loader Heap 上的地址,将对象与其动态
6、方法列表相关联起来,因此方法表是先于对象而存在的。类似于字段的创建过程,方法表的创建也是父类在先子类在后,原因是显而易见的,类 Chicken 生成方法列表时,首先将 Bird 的所有方法拷贝一份,然后和 Chicken 本身的方法列表做以对比,如果有覆写的虚方法则以子类方法覆盖同名的父类方法,同时添加子类的新方法,从而创建完成 Chicken的方法列表。这种创建过程也是逐层递归到 Object 类,并且方法列表中也是按照顺序排列的,父类子类在后,其原因和字段大同小异,留待读者自己体味。结合如下:的分析过程,现在将对象创建的过程以简单的图例来揭示其在内存中的分配情形,htt/从下的分析,和上面
7、的对象创建过程可见,对继承的本质有了更明确的认识,对于以就有了清晰明白的:继承是可传递的,子类是对父类的扩展,必须继承父类方法,同时可以添加新方法。子类可以调用父类方法和字段,而父类不能调用子类方法和字段。虚方法如何实现覆写操作,使得父类指针可以指向子类对象成员。new 关键字在虚方法继承中的阻断作用。你是否已经找到了理解继承、理解动态编译的不二。3. 思考通过上面的讲述与分析,基本上对.NET 在编译期的实现原理有了大致的了解,但是还有以下,一定会引起一定的疑惑,那就是:(OXJ HOXJ # TK )NOIQKT !这种情况下,bird2.ShowType 应该返回什么值呢?而 bird2
8、.type 有该是什么值呢?有两个原则,是.NET 专门用于解决这一问题的:关注对象原则:调用子类还是父类的方法,取决于创建的对象是子类对象还是父类对象,而不是它的类型。例如 Bird bird2 = new Chicken()时,关注的是其创建对象为 Chicken 类型,因此子类将继承父类的字段和方法,或者覆写父类的虚方法,而不用关注 bird2 的类型是否为 Bird。类型不同的区别决定了不同的对象在方法表中不同的权限。注意根据关注对象原则,那么下面的两种情况又该如何区别呢?根据上文的分析,bird2 对象和 chicken 对象在内存布局上是一样的,差别就在于其指针的类型不同:bird
9、2 为 Bird 类型指针,而 chicken 为 Chicken 类型指针。以方法调用为例,不同的类型指针在虚拟方法表中有不同的附加信息作为标志来区别其的地址区域,称为 offset。不同类型的指针只能在其特定地址区域内进行执行,子类覆盖父类时会保证其地址区域的一致性,从而解决了不同的类型具有不同的权限问题。(OXJ HOXJ # TK )NOIQKT !)NOIQKT INOIQKT # TK )NOIQKT !执行就近原则:对于同名字段或者方法,编译器是按照其顺序查找来的,也就是首先 离它创建最近的字段或者方法,例如上例中的 bird2,是 Bird 类型,因此会首先 Bird_type
10、(注意编译器是不会重新命名的,在此是为区分起见),如果 t ype 类型设为 public,则在此将返回“Bird”值。这也就是为什么在对象创建时必须将字段按顺序排列,而父类要先于子类编译的原因了。思考1.分析到 bird2.type 的值是“Bird”,那么 bird2.ShowType()会显示什么值呢?上面是“Type is Chicken”,根据本文上面的分析,想想到底为什么?2.关于 new 关键字在虚方法动态调用中的阻断作用,也有了更明确的理论基础。在子类方法中,如果标记 new 关键字,则意味着隐藏基类实现,其实就是创建了与父类同名的另一个方法,在编译中这两个方法处于动态方法表的不同地址位置,父类方法排法排在后面。面,子类方4. 结论在.NET 中,如果创建一个类,则该类总是在继承。这缘于.NET
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 收银系统操作规范数据核对流程
- 科学减脂餐食搭配配餐指引
- 慢病风险筛查操作手册
- 火龙罐温通疗法操作手册
- 茶叶科学采摘与留叶技术规范
- 重点客户档案建立管理操作规范
- 厂内交通突发事件处置规定
- 花卉基质育苗技术规程
- 现场突发事件应急处理标准流程
- 玉米螟综合防治管理规范
- 2025-2030中国辣椒产业标准化建设与质量管控体系报告
- 硝酸银安全使用技术说明书
- 2026年人教版化学中考知识点必背(精简版直击考点)
- 山东省青岛市2026届高三下学期高考一模语文试题
- 景区防汛责任制度
- 2026年疾病预防控制中心《食品安全》预测试卷
- 浙江省新阵地教育联盟2026届高三第二次联考数学试卷+答案
- 电厂劳动防护培训课件
- 深度解析(2026)《NBT 11481-2024 直流输电换流阀冷却设备控制保护系统技术要求》
- 化妆品包装设计核心要素
- 护理危机管理与应对
评论
0/150
提交评论