(2)继承关系中的多态性编译时与运行时

继承关系的类定义 1

class C

    {

        public virtual void C_M_Public() { Console.WriteLine("C::C_M_Public()"); }

    }

    class C1 : C

    {  

        public override void C_M_Public() { Console.WriteLine("C1::C_M_Public()"); }

    }

    class C11 : C1

    {

        public overrid  void C_M_Public() { Console.WriteLine("C11::C_M_Public()"); }

}

测试代码

    class Test

    {

        static void Main(string[] args)

        {  

//说明:整个过程生成的是C11类型的对象,转换的只是对象的引用类型

            C11 c11_c11 = new C11(); //C11C11对象

            C1 c1_c11 = (C1)c11_c11; //C1---C11对象

            C c_c11 = (C)c11_c11;   // C----C11对象

 

            c_c11.C_M_Public();

           c1_c11.C_M_Public();

          c11_c11.C_M_Public();

          }  

}

 

定义1测试结果如下:override

C11::C_M_Public()

C11::C_M_Public()

C11::C_M_Public()

请按任意键继续. . .

 

 

继承关系的类定义  

class C

    {

        public virtual void C_M_Public() { Console.WriteLine("C::C_M_Public()"); }

    }

    class C1 : C

    {  

        public override void C_M_Public() { Console.WriteLine("C1::C_M_Public()"); }

    }

    class C11 : C1

    {

        public new   void C_M_Public() { Console.WriteLine("C11::C_M_Public()"); }

}

 

测试代码

    class Test

    {

        static void Main(string[] args)

        {  

//说明:整个过程生成的是C11类型的对象,转换的只是对象的引用类型

            C11 c11_c11 = new C11(); //C11C11对象

            C1 c1_c11 = (C1)c11_c11; //C1---C11对象

            C c_c11 = (C)c11_c11;   // C----C11对象

 

            c_c11.C_M_Public();

           c1_c11.C_M_Public();

          c11_c11.C_M_Public();

          }  

}

 

定义2的测试结果如下:new 这个测试结果本人刚开始有点纳闷(还是因为理解不深,也不知道这东西到底有多深)

运行结果如下:

C1::C_M_Public()   ?????引用时C类型,实例对象是C11类型,调用的却是C1类型的方法???????

C1::C_M_Public()

C11::C_M_Public()

请按任意键继续. . .

 

个人分析:

我们看看MianIL代码如下:

.method private hidebysig static void  Main(string[] args) cil managed

{

  .entrypoint

  // 代码大小       33 (0x21)

  .maxstack  1

  .locals init ([0] class InheritTest.C11 c11_c11,

           [1] class InheritTest.C1 c1_c11,

           [2] class InheritTest.C c_c11)

  IL_0000:  nop

  IL_0001:  newobj     instance void InheritTest.C11::.ctor()

  IL_0006:  stloc.0

  IL_0007:  ldloc.0

  IL_0008:  stloc.1

  IL_0009:  ldloc.0

  IL_000a:  stloc.2

  IL_000b:  ldloc.2

  IL_000c:  callvirt   instance void InheritTest.C::C_M_Public()// C 虚方法,运行时多态性

  IL_0011:  nop

  IL_0012:  ldloc.1

  IL_0013:  callvirt   instance void InheritTest.C::C_M_Public()//C1 override虚方法,运行时多态性

  IL_0018:  nop

  IL_0019:  ldloc.0

  IL_001a:  callvirt   instance void InheritTest.C11::C_M_Public()// C11 new 编译时确定要调用的方法,编译时多态性

  IL_001f:  nop                                                             

IL_0020:  ret

} // end of method Test::Main

 

针对用C类型引用调用该方法时,它却调用了C1类型的该方法 实例对象可是C11类型的阿 个人分析原因如下:

 C#编译器编译后,这个方法调用被标记为虚方法调用,具体要调用什么方法要等到运行时指向的实例对象是什么类型,测试中 在运行时我们生成的是C11类型的实例对象,C11类型本身可并没有override这个方法,只有new 这个方法,但它的基类C1却有override这个方法,所以调用了它的基类C1的该方法;

 

这样的分析如果有不足,请大家多多指教!!至于CLR是如何来实现虚方法的调用,本人的理解还没有到那个层次。

 

 

 

 

 

 

原文地址:https://www.cnblogs.com/lzh/p/744817.html