当前位置:编程学习 > C#/ASP.NET >>

关于C#中的虚方法的问题

一直以来都对面向对象的语言如何实现虚方法和重写的这些问题很感兴趣,虽然知道最基本的一些如何使用这种设计方式,但是却一直没有找到一个详细的资料告诉我C#到底是如何做到的。
最近没什么事情就把一直想看的<<essential .net>>这本书翻了一下,让我对这件事有了一定程度了解(至少我认为是这样)。
     因为这个问题会涉及到方法表,所以我认为应该先把对象如何在内存中存储的来做一个简单的介绍。下面就是一张说明对象的存储的图(完全是从书上来的),
 

\


假设我们有这样一个声明语句: Human b = new Human();
那么object reference就是我们声明的变量b, 他就是一个指针, 他指向的位置就是一个对象真正被存储的地方Object(Human)。在这块区域上主要有三个部分, 第一个部分是一个对这个对象的索引,具体的功能我还不清楚,但是他在这里没有用到,所以可以忽略。第二部分htype是一个指针, 他指向的位置存储的是这个实例所属的类的信息。 第三部分是存储这个类的数据成员。
在这里重点是关于第二个指针htype的。htype指向的区域被作者称为CORINFO_CLASS_STRUCT, 对于每一个类都有这样一个区域,而且应该是唯一的。在CORINFO_CLASS_STRUCT这块区域中,只要知道有一下三个区域就可以了:
 

  1. 存有指向父类的CORINFO_CLASS_STRUCT区域的指针,如果有父类的话。
  2. 有一个指向接口表的指针,接口表中存放的就是该类型继承的接口的htype
  3. 方法表

有了前两项内容就建立起来类与类之间的关系了,对象的类型转换就是通过这个来判断的,但我们关注的主要还是方法表。
为了配合问题的说明,我定义了两个简单的类Base和Child。Base 中的方法大部分都是虚方法, 然后在Child中也定义相同的方法,但是前面的修饰符不同。

 
1  public class A
 2    {
 3        static void Main()
 4        {
 5            Base b = new Child();
 6            Child ch = new Child();
 7
 8            b.print();
 9            b.print2();
10            b.print3();
11            b.print4();
12
13            ch.print();
14            ch.print2();
15            ch.print3();
16            ch.print4();
17
18            Console.ReadKey();
19        }
20    }
21
22    public class Base
23    {
24        public int x = 8;
25
26        public Base() { }
27
28
29        public void print()
30        {
31            Writer.OutPut("a");
32        }
33
34        public virtual void print2()
35        {
36            Writer.OutPut("b");
37        }
38
39        public virtual void print3()
40        {
41            Writer.OutPut("c");
42        }
43
44        public virtual void print4()
45        {
46            Writer.OutPut("d");
47        }
48
49    }
50
51    public class Child : Base
52    {
53        public Child() { }
54        public void print()
55        {
56            Writer.OutPut("e");
57        }
58
59        public override void print2()
60        {
61            Writer.OutPut("f");
62        }
63        public new virtual void print3()
64        {
65            Writer.OutPut("g");
66        }
67        public virtual void print4()
68        {
69            Writer.OutPut("h");
70        }
71    }

这段程序在被编译成IL后, 我们可以看一下main方法是怎么样的
 

 

 

 1.method private hidebysig static void Main() cil managed
 2{
 3    .entrypoint
 4    .maxstack 1
 5    .locals init (
 6        [0] class FormatNumber.Base b,
 7        [1] class FormatNumber.Child ch)
 8    L_0000: nop
 9    L_0001: newobj instance void FormatNumber.Child::.ctor()
10    L_0006: stloc.0
11    L_0007: newobj instance void FormatNumber.Child::.ctor()
12    L_000c: stloc.1
补充:软件开发 , C# ,

CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,