• (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是如何来实现虚方法的调用,本人的理解还没有到那个层次。

     

     

     

     

     

     

  • 相关阅读:
    vuex 按需动态引入等常用写法
    golang堆栈信息
    fiber框架
    leveldb查看工具
    golang sdk报错
    csdn复制问题
    golang panic打印
    unix socket 抓包
    dlv远程调试
    gitsubmodule使用
  • 原文地址:https://www.cnblogs.com/lzh/p/744817.html
Copyright © 2020-2023  润新知