zoukankan      html  css  js  c++  java
  • 学习C#虚函数实例演示

    在C++、Java等众多OOP语言里都可以看到virtual的身影,而C#作为一个完全面向对象的语言当然也不例外。

    C#虚函数从程序编译的角度来看,它和其它一般的函数有什么区别呢?一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,也就是写死了的!而C#虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它会根据运行时期对象实例来动态判断要调用的函数,其中那个申明时定义的类叫申明类,那个执行时实例化的类叫实例类。

    如:飞禽 bird = new 麻雀();

    那么飞禽就是申明类,麻雀是实例类。

    具体的检查的流程如下

    1、当调用一个对象的函数时,系统会直接去检查这个对象申明定义的类,即申明类,看所调用的函数是否为C#虚函数;

    2、如果不是虚函数,那么它就直接执行该函数。而如果有virtual关键字,也就是一个虚函数,那么这个时候它就不会立刻执行该函数了,而是转去检查对象的实例类。

    3、在这个实例类里,他会检查这个实例类的定义中是否有重新实现该虚函数(通过override关键字),如果是有,那么OK,它就不会再找了,而马上执行该实例类中的这个重新实现的函数。而如果没有的话,系统就会不停地往上找实例类的父类,并对父类重复刚才在实例类里的检查,直到找到第一个重载了该虚函数的父类为止,然后执行该父类里重载后的函数。

    1. using System;  
    2.  
    3. namespace Zhisi.Net  
    4. {  
    5.     class A  
    6.     {  
    7.         public virtual void Func() // 注意virtual,表明这是一个虚拟函数  
    8.         {  
    9.             Console.WriteLine("Func In A");  
    10.         }  
    11.     }  
    12.  
    13.     class B : A // 注意B是从A类继承,所以A是父类,B是子类  
    14.     {  
    15.         public override void Func() // 注意override ,表明重新实现了虚函数  
    16.         {  
    17.             Console.WriteLine("Func In B");  
    18.         }  
    19.     }  
    20.  
    21.     class C : B // 注意C是从A类继承,所以B是父类,C是子类  
    22.     {  
    23.     }  
    24.  
    25.     class D : A // 注意B是从A类继承,所以A是父类,D是子类  
    26.     {  
    27.         public new void Func() // 注意new ,表明覆盖父类里的同名类,而不是重新实现  
    28.         {  
    29.             Console.WriteLine("Func In D");  
    30.         }  
    31.     }  
    32.  
    33.     class program  
    34.     {  
    35.         static void Main()  
    36.         {  
    37.             A a;         // 定义一个a这个A类的对象.这个A就是a的申明类  
    38.             A b;         // 定义一个b这个A类的对象.这个A就是b的申明类  
    39.             A c;         // 定义一个c这个A类的对象.这个A就是b的申明类  
    40.             A d;         // 定义一个d这个A类的对象.这个A就是b的申明类  
    41.  
    42.             a = new A(); // 实例化a对象,A是a的实例类  
    43.             b = new B(); // 实例化b对象,B是b的实例类  
    44.             c = new C(); // 实例化b对象,C是b的实例类  
    45.             d = new D(); // 实例化b对象,D是b的实例类  
    46.  
    47.             a.Func();    // 执行a.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类A,就为本身 4.执行实例类A中的方法 5.输出结果 Func In A  
    48.             b.Func();    // 执行b.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重载的 4.执行实例类B中的方法 5.输出结果 Func In B  
    49.             c.Func();    // 执行c.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重载的 4.转去检查类C的父类B,有重载的 5.执行父类B中的Func方法 5.输出结果 Func In B  
    50.             d.Func();    // 执行d.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类D,无重载的(这个地方要注意了,虽然D里有实现Func(),但没有使用override关键字,所以不会被认为是重载) 4.转去检查类D的父类A,就为本身 5.执行父类A中的Func方法 5.输出结果 Func In A  
    51.             D d1 = new D();  
    52.             d1.Func(); // 执行D类里的Func(),输出结果 Func In D  
    53.             Console.ReadLine();  
    54.         }  
    55.     }  
  • 相关阅读:
    windows的80端口被占用时的处理方法
    Ansible自动化运维工具安装与使用实例
    Tomcat的测试网页换成自己项目首页
    LeetCode 219. Contains Duplicate II
    LeetCode Contest 177
    LeetCode 217. Contains Duplicate
    LeetCode 216. Combination Sum III(DFS)
    LeetCode 215. Kth Largest Element in an Array(排序)
    Contest 176 LeetCode 1354. Construct Target Array With Multiple Sums(优先队列,递推)
    Contest 176
  • 原文地址:https://www.cnblogs.com/xuanqust/p/1739057.html
Copyright © 2011-2022 走看看