[Programming IL]虚方法,重载,抽象方法,覆盖 - Virtual Methods, Overload, Abstract, Override

引言

前面我们讲到了接口,类,流程控制,那面向对象的一些基本概念,重载,覆盖,抽象/虚方法这些概念在.Net中又是如何实现的呢?

概念

可能提了无数次了,然后还是要定义一下, 温故而知新嘛. :) 这些面向对象的基本元素都是和方法联系在一起。方法由方法头(Method Header)和方法体(Method Body)组成,方法头由 ( 修饰符,返回值,方法名,定义域修饰符(internal), 参数列表,方法Attribute )组成. 而方法体里的内容比较复杂

方法项 描述
.custom CustomDecl 定义自定义标签(Attributes)
.data DataDecl 将数据存在在PE中
.emitbyte Int32 将一个8位的Unsigned byte生成到方法的.code段中,该标志只适用于生成测试,并不会在常规程序中出现
.entrypoint 前面已经有提及,标志方法为入口点

.locals [ init ] method.

初始化方法中的一些字段. 例子:
.locals init ( int32 i, int32 j, float32 f, int64[] vect)
.maxstack Int32 定义在执行栈上最多存放多少个元素
.override
TypeSpec:: MethodName


.override method CallConv Type TypeSpec::!MethodName GenArity (with method CallConv Type TypeSpec::!MethodName GenArity
Parameters)

为子类的虚方法或者接口方法提供具体实现. 在编译成PE则会存放在MethodImpl表中.  例子:

.class interface I
{ .method public virtual abstract void M() cil managed {}
}
.class C implements I
{ .method virtual public void M2()
  { // body of M2
  }
  .override I::M with instance void C::M2()
}

.param [Int32] [=FieldInit] Int32代表参数索引,注意: 0 代表返回类型
.param type [ Int32 ] 泛型参数,当位于泛型类中,由类中的泛型类型来确定类型。 Sample:

.class public G<T,U> {
  .param type [1]  // refers to T
  .custom instance void TypeParamAttribute::.ctor() = (01 00 ... )
  .method public void Foo<M>(m) {
     .param type [1] // refers to M
     .custom instance void AnotherTypeParamAttribute::.ctor() = (01 00 ... )
  }
}

ExternSourceDecl .line 指向代码中的其他行
Instr 一个对String进行操作的指令
Id : 标签Label
ScopeBlock 代码段
SecurityDecl .permission or .permissionset, 权限验证
SEHBlock SEH = 结构化异常处理,异常处理块

这里提到了override, 那么abstract 和 virtual 呢? 这里这些指令要放在一起. 我们从一个例子开始吧

从例子开始

代码:

   1: using System;
   2: public class Testing
   3: {    
   4:     public static void Main()
   5:     {
   6:         // Use The Bae Type To Call The Methods
   7:         MyBase base1 = new MyChild();
   8:         base1.BaseFunction();
   9:         base1.BaseFun2();        
  10:         
  11:         // Use The Child Type to call the methods
  12:         MyChild child = new MyChild();
  13:         child.BaseFun2();
  14:         child.Fun();
  15:         child.Fun("XWang");
  16:         
  17:         // Abstract - Override Implemention
  18:         MyAbstractBase base2 = new MyConcerateClass();
  19:         base2.MyAbastractFun();            
  20:         
  21:         Console.ReadKey();
  22:     }
  23: }
  24:  
  25: public class MyBase
  26: {
  27:     public virtual void BaseFunction()
  28:     {
  29:         Console.WriteLine("This is the BaseFunction In MyBase");
  30:     }            
  31:     
  32:     public virtual void BaseFun2()
  33:     {
  34:         Console.WriteLine("This is the BaseFun2 In MyBase");
  35:     }
  36: }
  37:  
  38: public class MyChild : MyBase
  39: {
  40:     // Virual - Override 
  41:     public override void BaseFunction()
  42:     {
  43:         Console.WriteLine("This is the BaseFunction in MyChild");
  44:     }
  45:     
  46:     // NewsLot Method
  47:     public new void BaseFun2()
  48:     {
  49:         Console.WriteLine("This is the new BaseFun2 in MyChild");
  50:     }        
  51:     
  52:     // OverLoad        
  53:     public void Fun()
  54:     {
  55:         Console.WriteLine("This is the Fun In MyChild");
  56:     }
  57:     
  58:     public void Fun(string name)
  59:     {
  60:         Console.WriteLine("This is the Fun(string name) in MyChild. Hello: {0}", name);
  61:     }
  62: }
  63:  
  64: public abstract class MyAbstractBase
  65: {
  66:     public abstract void MyAbastractFun();
  67: }
  68:  
  69: public class MyConcerateClass : MyAbstractBase
  70: {
  71:     // Abstarct - Override
  72:     public override void MyAbastractFun()
  73:     {
  74:         Console.WriteLine("This is implemention of MyAbastractFun in MyChild");
  75:     }
  76:     
  77: }

看看结果:

image 

好像有点乱,我们做个表对应分析一下 

方法 执行结果
base1.BaseFunction(); This is the BaseFunction in MyChild
base1.BaseFun2(); This is the BaseFun2 In MyBase
child.BaseFun2(); This is the new BaseFun2 in MyChild
child.Fun(); This is the Fun In MyChild
child.Fun("XWang"); This is the Fun(string name) in MyChild. Hello: XWang
base2.MyAbastractFun();  This is implemention of MyAbastractFun in MyChild

规律:

1. Virtual 和 Abstract和Override之后都会执行子类的实现

2. 当有new做标记时,不会跳转到子类的实现,两个类相对独立

亲爱的读者,你想不想探索一下呢?Follow me:

反编译

代码太长, 觉得麻烦下面抽重点分析

   1: .class public auto ansi beforefieldinit MyBase
   2:        extends [mscorlib]System.Object
   3: {
   4:   .method public hidebysig newslot virtual 
   5:           instance void  BaseFunction() cil managed
   6:   {
   7:     // Code size       11 (0xb)
   8:     .maxstack  8
   9:     IL_0000:  ldstr      "This is the BaseFunction In MyBase"
  10:     IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
  11:     IL_000a:  ret
  12:   } // end of method MyBase::BaseFunction
  13:  
  14:   .method public hidebysig newslot virtual 
  15:           instance void  BaseFun2() cil managed
  16:   {
  17:     // Code size       11 (0xb)
  18:     .maxstack  8
  19:     IL_0000:  ldstr      "This is the BaseFun2 In MyBase"
  20:     IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
  21:     IL_000a:  ret
  22:   } // end of method MyBase::BaseFun2
  23:  
  24:   .method public hidebysig specialname rtspecialname 
  25:           instance void  .ctor() cil managed
  26:   {
  27:     // Code size       7 (0x7)
  28:     .maxstack  8
  29:     IL_0000:  ldarg.0
  30:     IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
  31:     IL_0006:  ret
  32:   } // end of method MyBase::.ctor
  33:  
  34: } // end of class MyBase
  35:  
  36: .class public auto ansi beforefieldinit MyChild
  37:        extends MyBase
  38: {
  39:   .method public hidebysig virtual instance void 
  40:           BaseFunction() cil managed
  41:   {
  42:     // Code size       11 (0xb)
  43:     .maxstack  8
  44:     IL_0000:  ldstr      "This is the BaseFunction in MyChild"
  45:     IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
  46:     IL_000a:  ret
  47:   } // end of method MyChild::BaseFunction
  48:  
  49:   .method public hidebysig instance void 
  50:           BaseFun2() cil managed
  51:   {
  52:     // Code size       11 (0xb)
  53:     .maxstack  8
  54:     IL_0000:  ldstr      "This is the new BaseFun2 in MyChild"
  55:     IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
  56:     IL_000a:  ret
  57:   } // end of method MyChild::BaseFun2
  58:  
  59:   .method public hidebysig instance void 
  60:           Fun() cil managed
  61:   {
  62:     // Code size       11 (0xb)
  63:     .maxstack  8
  64:     IL_0000:  ldstr      "This is the Fun In MyChild"
  65:     IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
  66:     IL_000a:  ret
  67:   } // end of method MyChild::Fun
  68:  
  69:   .method public hidebysig instance void 
  70:           Fun(string name) cil managed
  71:   {
  72:     // Code size       12 (0xc)
  73:     .maxstack  8
  74:     IL_0000:  ldstr      "This is the Fun(string name) in MyChild. Hello: {0}"
  75:     IL_0005:  ldarg.1
  76:     IL_0006:  call       void [mscorlib]System.Console::WriteLine(string,
  77:                                                                   object)
  78:     IL_000b:  ret
  79:   } // end of method MyChild::Fun
  80:  
  81:   .method public hidebysig specialname rtspecialname 
  82:           instance void  .ctor() cil managed
  83:   {
  84:     // Code size       7 (0x7)
  85:     .maxstack  8
  86:     IL_0000:  ldarg.0
  87:     IL_0001:  call       instance void MyBase::.ctor()
  88:     IL_0006:  ret
  89:   } // end of method MyChild::.ctor
  90:  
  91: } // end of class MyChild
  92:  
  93: .class public abstract auto ansi beforefieldinit MyAbstractBase
  94:        extends [mscorlib]System.Object
  95: {
  96:   .method public hidebysig newslot abstract virtual 
  97:           instance void  MyAbastractFun() cil managed
  98:   {
  99:   } // end of method MyAbstractBase::MyAbastractFun
 100:  
 101:   .method family hidebysig specialname rtspecialname 
 102:           instance void  .ctor() cil managed
 103:   {
 104:     // Code size       7 (0x7)
 105:     .maxstack  8
 106:     IL_0000:  ldarg.0
 107:     IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
 108:     IL_0006:  ret
 109:   } // end of method MyAbstractBase::.ctor
 110:  
 111: } // end of class MyAbstractBase
 112:  
 113: .class public auto ansi beforefieldinit MyConcerateClass
 114:        extends MyAbstractBase
 115: {
 116:   .method public hidebysig virtual instance void 
 117:           MyAbastractFun() cil managed
 118:   {
 119:     // Code size       11 (0xb)
 120:     .maxstack  8
 121:     IL_0000:  ldstr      "This is implemention of MyAbastractFun in MyChild"
 122:     IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
 123:     IL_000a:  ret
 124:   } // end of method MyConcerateClass::MyAbastractFun
 125:  
 126:   .method public hidebysig specialname rtspecialname 
 127:           instance void  .ctor() cil managed
 128:   {
 129:     // Code size       7 (0x7)
 130:     .maxstack  8
 131:     IL_0000:  ldarg.0
 132:     IL_0001:  call       instance void MyAbstractBase::.ctor()
 133:     IL_0006:  ret
 134:   } // end of method MyConcerateClass::.ctor
 135:  
 136: } // end of class MyConcerateClass

对应的IL解释

方法 ILAsm
base1.BaseFunction();

[MyBase]:  .method public hidebysig newslot virtual instance void  BaseFunction() cil managed

[MyChild]: .method public hidebysig virtual instance void           BaseFunction() cil managed

base1.BaseFun2();

[MyBase/MyChild].method public hidebysig newslot virtual instance void  BaseFun2() cil managed

child.BaseFun2(); [MyChild]: .method public hidebysig instance void BaseFun2() cil managed
child.Fun(); [MyChild]: .method public hidebysig instance void Fun() cil managed
child.Fun("XWang"); [MyChild]: .method public hidebysig instance void Fun(string name) cil managed
base2.MyAbastractFun();  [MyChild] .method public hidebysig virtual instance void          MyAbastractFun() cil managed

[MyBase] .method public hidebysig newslot abstract virtual       instance void  MyAbastractFun() cil managed

可以看到父类的Virtual和子类的实现差别在于  newslot virtual,我们看看对于这个指令的解释

If the class defines any public virtual newslot methods whose name and
signature match a virtual method on the interface, then use these new virtual methods
to implement the corresponding interface method.

当在方法前定义newslot virtual则当他们实现中碰到同样签名的方法时则立即执行跳转,关于内存结构的部分,之前有讲到, 指令上则是call 和 callvirt 的差别

到这里我想该有的基础都有了,那么正式开始我们的IL 程序吧. :)

代码如下:

   1: .assembly extern mscorlib {}
   2: .assembly OOPSample {}
   3: .module OOP.exe
   4: .class public auto ansi Testing extends [mscorlib]System.Object
   5: {
   6:     .method public static void Main() cil managed
   7:     {
   8:         .entrypoint
   9:         .maxstack 2
  10:         .locals init (class MyBase V_0)
  11:         newobj        instance void MyChild::.ctor()
  12:         stloc.0
  13:         ldloc.0
  14:         callvirt    instance void MyBase::MyBaseFun()
  15:  
  16:         ret
  17:     }    
  18: }
  19:  
  20: // define the base class
  21: .class public auto MyBase extends [mscorlib]System.Object
  22: {
  23:     .method public newslot virtual instance void MyBaseFun() cil managed
  24:     {
  25:         .maxstack 8
  26:         ldstr "This is the MyBaseFun In MyBase"
  27:         call    void [mscorlib]System.Console::WriteLine(string)
  28:         ret
  29:     }
  30:     
  31:     .method public specialname rtspecialname instance void .ctor() cil 
  32:  
  33: managed
  34:     {
  35:         .maxstack 8
  36:         ldarg.0
  37:         call       instance void [mscorlib]System.Object::.ctor()
  38:         ret
  39:     }
  40: }
  41:  
  42: // Define the Concerate Implemention
  43: .class public auto MyChild extends MyBase
  44: {
  45:     .method public virtual instance void MyBaseFun() cil managed
  46:     {
  47:         .maxstack 8
  48:         ldstr "This is the MyBaseFun In MyChild"
  49:         call    void [mscorlib]System.Console::WriteLine(string)
  50:         ret
  51:     }
  52:  
  53:     .method public specialname rtspecialname instance void .ctor() cil 
  54:  
  55: managed
  56:     {
  57:         .maxstack 8
  58:         ldarg.0
  59:         call        instance void MyBase::.ctor()
  60:         ret
  61:     }
  62: }

结果:

 image

结合本文开头介绍的方法理解这个应该不难,BTW: 这里还有最简单的Hello World版本哦

posted on 2008-09-21 02:20  xwang  阅读(538)  评论(0编辑  收藏  举报

导航