解析.net中继承的实质

在csdn论坛、博客园里都有很多帖子讨论c#中继承语法的问题,大家乐此不疲的解释 virtual,override,new,final,接口,类中的继承。各种各样的例子让新手头晕脑胀 ,这其中还一些地方以讹传讹。

比如这篇文章里面竟然说“编译器会顺着继承链往下找,一直找到合适的那个方法体 ”,在回复里还有人说“这个特征特现了C#编译器对里氏代换原则的支持。也就是:凡是 基类适用的地方子类一定适用。

比如class Base {},class Sub:base {} 如果:Base a=new Sub();那么实际上编译 器已经能够确定a所指向的对象的类型。所以方法的地址确实是在编译期就确定了的。” 。我真是无语了,override的实现本质上是非常简单的,但由于每次都是从语法的角度讨 论问题所以总是不得要领。

所以我这篇帖子的将从底层实现的角度来向你说明override的实现。首先让我们明确2 个概念:

1.类实例的方法调用都是虚调用(callvirt)只有在调用基类方法时是实调用(call )。请看代码:

1. class A
2.   {
3.     public void Boo()
4.     {
5.       Console.WriteLine("A::Boo().");
6.     }
7.      public virtual void Foo()
8.     {
9.       Console.WriteLine("A::Foo().");
10.     }
11.   }
12.   class B : A
13.   {
14.     public override void Foo()
15.     {
16.       Console.WriteLine("B::Foo().");
17.       base.Foo();
18.     }
19.   }
20.   class Class1
21.   {
22.     public static void Main()
23.     {
24.       A a = new A();
25.       a.Foo();
26.       a.Boo();
27.        A b = new B();
28.       a.Foo();
29.       a.Boo();
30.     }
31.   }

让我看一下对应的IL代码片段

1. //main函数,调用实例函数的IL
2. //a.Foo();
3. IL_0007:  callvirt  instance void test_console.A::Foo()
4. //a.Boo();
5. IL_000d:  callvirt  instance void test_console.A::Boo()
6. //b.Foo();
7. IL_0019: callvirt  instance void test_console.A::Foo()
8. //b.Boo ();
9. IL_001f: callvirt  instance void test_console.A::Boo()
10.
11. //B类中Foo函数
12. IL_0000: ldstr   "B::Foo()."
13.   IL_0005: call    void [mscorlib]System.Console::WriteLine(string)
14.  IL_000a: ldarg.0
15.  //base.Foo();
16.  IL_000b: call     instance void test_console.A::Foo()
17.  IL_0010: ret

时间: 2024-08-02 19:04:58

解析.net中继承的实质的相关文章

java-fastjson在反序列化时,怎么解析对象中的继承

问题描述 fastjson在反序列化时,怎么解析对象中的继承 例子: import com.alibaba.fastjson.JSON; public class Text { private A a; class A { private String a; public String getA() { return a; } public void setA(String a) { this.a = a; } } class B extends A { private String b; pu

详细解析Python中

  这篇文章主要介绍了详细解析Python中__init__()方法的高级应用,包括在映射和elif序列等地方的更为复杂的用法,需要的朋友可以参考下 通过工厂函数对 __init__() 加以利用 我们可以通过工厂函数来构建一副完整的扑克牌.这会比枚举所有52张扑克牌要好得多,在Python中,我们有如下两种常见的工厂方法: 定义一个函数,该函数会创建所需类的对象. 定义一个类,该类有创建对象的方法.这是一个完整的工厂设计模式,正如设计模式书所描述的那样.在诸如Java这样的语言中,工厂类层次结

对象-oc 类的继承的实质,以及是怎样调用方法 和函数的

问题描述 oc 类的继承的实质,以及是怎样调用方法 和函数的 父类里声明的属性,会生成默认生成一个私有的成员变量.即不能被子类访问,那么子类通过继承得到了父类的属性,只能通过setter 和 getter 方法区访问父类的私有变量,那么这个私有变量不属于子类,那么在实例化这个子类的时候就没有这个私有变量,那么通过继承过来的setter 和getter方法访问的是什么,私有变量根本就没有生成啊! 同理在使用{}声明的私有变量同样可以在提供外部接口让外部访问,但是当子类继承后也可以通过生成实例对象,

JavaScript解析:HTM中嵌入嵌入JavaScript语言引擎

文章简介:JavaScript解析:让搜索引擎看到更真实的网页. 长期以来,站长们选择使用JavaScript来实现网页的动态行为,这样做的原因是多种多样的,如加快页面的响应速度.降低网站流量.隐藏链接或者嵌入广告等.由于早期的搜索引擎没有相应的处理能力,导致在索引这类网页上往往出现问题,可能无法收录有价值的资源,也可能出现作弊. 引入JavaScript解析的目的,正是为了解决上述两方面的问题,其结果也就是使搜索引擎可以更为清晰的了解用户实际打开该网页时看到的效果.比如有些网站会将用户评论.评

解析css中30个最常用的选择器

文章简介:30个最常用css选择器解析. 你也许已经掌握了id.class.后台选择器这些基本的css选择器.但这远远不是css的全部.下面向大家系统的解析css中30个最常用的选择器,包括我们最头痛的浏览器兼容性问题.掌握了它们,才能真正领略css的巨大灵活性. 1. * {    margin: 0;    padding: 0;   } 星状选择符会在页面上的每一个元素上起作用.web设计者经常用它将页面中所有元素的margin和padding设置为0. *选择符也可以在子选择器中使用.

微信公众帐号开发教程(十) 解析接口中的消息创建时间CreateTime

从微信公众平台的消息接口指南中可以看出,每种类型的消息定义中,都包含有CreateTime参数,它表示 消息的创建时间,如下图所示: 开发教程(十) 解析接口中的消息创建时间CreateTime-create time"> 上图是消息接口指南中4.1-文本消息的定义.注意CreateTime的描述:消息创建时间(整型),重点在于 这是一个整型的时间,而不是我们大家所熟悉的类似于"yyyy-MM-dd HH:mm:ss"的标准格式时间. 本文主要想介绍的就是微信消息接口中

Java语言入门教程(十三):Java语言中继承中的构造方法问题

教程(十一)中,了解了Java语言中继承的基本概念.Java中类与类的继承 ,是单继承,主要目的是复用.子类对象可以复用父类中权限允许的属性和方法 ,所以子类的构造方法和父类的构造方法之间,有一定的调用关系,本文中将进 行详细介绍. 首先,需要记住一个事实:子类的任何一个构造方法,都将先调用父类某个 构造方法.如子类Trainer中的构造方法: public Trainer() { } 虽然这个构造方法的方法体中什么代码也没有写,但是也调用了父类 Employee的构造方法,默认调用的是Empl

JavaScript中继承用法实例分析

  本文实例分析了JavaScript中继承的用法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 // define the Person Class function Person() {} Person.prototype.walk = function(){ alert ('I am walking!'); }; Person

详细解析Ruby中的变量

这篇文章主要介绍了详细解析Ruby中的变量,是Ruby学习中最基础的知识之一,需要的朋友可以参考下 变量持有要使用的程序的数据的存储位置. Ruby支持的有五种类型的变量.在前面的章节中已经经历了一个简短描述以及这些变量.本章中介绍的这五种类型的变量. Ruby的全局变量: 全局变量以$开头.未初始化的全局变量的值是零,并使用-w选项产生警告. 全局变量的赋值会改变全局状态.这是不推荐使用全局变量.他们使得程序的含义模糊. 下面是一个例子显示使用全局变量. ? 1 2 3 4 5 6 7 8 9