zoukankan      html  css  js  c++  java
  • C# virtual,override,new 整理

    今天仔细学习了一下C#中virtual, override, new关键字,参考了网上的很多资料,现整理一下。

    Virtual:

    virtual 关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。默认情况下,方法是非虚拟的。不能重写非虚方法。virtual 修饰符不能与 staticabstract, privateoverride 修饰符一起使用。

    Override:

    override 方法提供从基类继承的成员的新实现。由 override 声明重写的方法称为重写基方法。重写的基方法必须与 override 方法具有相同的签名。重写的基方法必须是vitural,override,abstract类型的 ,不能重写非虚方法或是静态方法,所以override不能与vitural,new,static同时使用

    override 属性必须指定与继承属性完全相同的访问修饰符、类型和名称,并且被重写的属性必须是 virtualabstractoverride 的。

    New:

    new 修饰符显式隐藏从基类继承的成员(即隐藏父类同签名方法)。 不标识时虽会出现编译警告,不影响使用

    ---------------------

    函数调用实际流程:

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

    如:飞禽 bird = new 麻雀();
    那么飞禽就是申明类,麻雀是实例类。

    具体的检查的流程如下

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

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

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

    知道这点,就可以理解下面代码的运行结果了:

     1 using System;  
     2 namespace Smz.Test  
     3 {  
     4     class A  
     5     {  
     6         public virtual void Func() // 注意virtual,表明这是一个虚拟函数  
     7         {  
     8             Console.WriteLine("Func In A");  
     9         }  
    10     }  
    11     class B : A // 注意B是从A类继承,所以A是父类,B是子类  
    12     {  
    13         public override void Func() // 注意override ,表明重新实现了虚函数  
    14         {  
    15             Console.WriteLine("Func In B");  
    16         }  
    17     }  
    18     class C : B // 注意C是从A类继承,所以B是父类,C是子类  
    19     {  
    20     }  
    21     class D : A // 注意B是从A类继承,所以A是父类,D是子类  
    22     {  
    23         public new void Func() // 注意new ,表明覆盖父类里的同名类,而不是重新实现。注意这里如果不用new,此时D的func就与父类A的func重名了,会出现一个警告,虽然程序仍然会调用A中的func,所以new能消除警告。  
    24         {  
    25             Console.WriteLine("Func In D");  
    26         }  
    27     }  
    28     class program  
    29     {  
    30         static void Main()  
    31         {  
    32             A a;         // 定义一个a这个A类的对象.这个A就是a的申明类  
    33             A b;         // 定义一个b这个A类的对象.这个A就是b的申明类  
    34             A c;         // 定义一个c这个A类的对象.这个A就是b的申明类  
    35             A d;         // 定义一个d这个A类的对象.这个A就是b的申明类  
    36             a = new A(); // 实例化a对象,A是a的实例类  
    37             b = new B(); // 实例化b对象,B是b的实例类  
    38             c = new C(); // 实例化b对象,C是b的实例类  
    39             d = new D(); // 实例化b对象,D是b的实例类  
    40             a.Func();    // 执行a.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类A,就为本身 4.执行实例类A中的方法 5.输出结果 Func In A  
    41             b.Func();    // 执行b.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重载的 4.执行实例类B中的方法 5.输出结果 Func In B  
    42             c.Func();    // 执行c.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重载的 4.转去检查类C的父类B,有重载的 5.执行父类B中的Func方法 5.输出结果 Func In B  
    43             d.Func();    // 执行d.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类D,无重载的(这个地方要注意了,虽然D里有实现Func(),但没有使用override关键字,所以不会被认为是重载) 4.转去检查类D的父类A,就为本身 5.执行父类A中的Func方法 5.输出结果 Func In A .   
    44             D d1 = new D();  
    45             d1.Func();   // 执行D类里的Func(),输出结果 Func In D  
    46             Console.ReadLine();  
    47         }  
    48     }  
    49 }  

    以上是我对virtual, override, new的整理。

  • 相关阅读:
    27. Remove Element
    26. Remove Duplicates from Sorted Array
    643. Maximum Average Subarray I
    674. Longest Continuous Increasing Subsequence
    1. Two Sum
    217. Contains Duplicate
    448. Find All Numbers Disappeared in an Array
    566. Reshape the Matrix
    628. Maximum Product of Three Numbers
    UVa 1349 Optimal Bus Route Design (最佳完美匹配)
  • 原文地址:https://www.cnblogs.com/yisss/p/3407136.html
Copyright © 2011-2022 走看看