zoukankan      html  css  js  c++  java
  • C# 虚函数virtual的使用

    一.前言

      在使用C#开发的过程中,我们经常可以看到virtual关键字,这个关键字具体的使用场景是有类做实现继承,父类通过virtual设置虚方法,子类可以通过override来重写该方法。

    二.编译原理

      一般函数在编译时就静态地编译到执行文件中,其相对地址在程序运行期间是不发生变化。虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它在运行期间根据对象实例来判断要调用的函数。

    三.实例讲解

    1.一般情况

      这是一般的类实现继承,A和B类,B类继承A类,在A类和B类中都同时有一个相同名字的方法,在执行时会有什么影响?

    public class A
    {
        public void Func()
        {
            Console.WriteLine("A");
        }
    }
    
    public class B : A
    {
        public void Func()
        {
            Console.WriteLine("B");
        }
    }
    
    //调用
    public static void Main(string[] args)
    {
        A a = new A();
        B b = new B();
    
        a.Func();
        b.Func();
    
        a = new B();
        a.Func();
    }

      输出的结果是。

    A
    B
    A

      第一个输出的结果是A,这个是毫无疑问的。

      第二个输出的结果是B,这是根据什么判断的?B类继承A类,如果两个类有同名的方法,那子类就会隐藏掉父类的同名方法。在编译器也会提醒是隐藏继承成员的方法,有意为之的话,可以使用关键字new。

      第三个输出的结果是A。这里先讲一下类申明、实例类的定义,如A a = new B();A为申明类,B为实例类。一般情况下,所调用的方法都是在申明类中的。

    2.使用virtual关键字

      在上面的例子第三个输出得知,实例化的对象去调用方法,如A a = new B(),且A、B类都有同名方法,一般情况下是调用申明类的方法。那其它情况就是有使用virtual关键字的情况了,使用了virtual关键字修饰的方法叫做虚方法。

      上面讲过使用了virtual关键字,编译器会对虚方法指向的地址做处理,具体检查流程如下。

      1.在调用对象的方法时,首先会判断该对象的申明类中的方法是否为虚方法,如果不是虚方法,那么就会直接调用。

      2.如果是虚方法,那么它就会检查它的实例类是否有重新实现这个虚方法(使用override关键字),如果有,就直接调用实例类这个重新实现的方法。如果没有,则依次上溯,按照同样步骤对父类进行检查,直到找到重新实现该虚方法的父类,并调用方法。

      例子:准备要使用的类。

    public class A
    {
        public virtual void Func()
        {
            Console.WriteLine("A");
        }
    }
    
    public class B : A
    {
        public override void Func()
        {
            Console.WriteLine("B");
        }
    }
    
    public class C : B
    {
    
    }
    
    public class D : A
    {
        public new void Func()
        {
            Console.WriteLine("D");
        }
    }

      

    //调用
    public static void Main(string[] args)
    {
        A c = new C();
        c.Func();
    }

      输出结果是B。检查到申明类A的是虚拟方法,转去检查实现类C。C类没有重写(override)方法,转为检查C类的父类B类,B类有重写该方法,调用该方法。

      另外,没有使用override的情况。

    //调用
    public static void Main(string[] args)
    {
        A d = new D();
        d.Func();
    }

      输出结果是A。虽然实现类有Func,但由于没有(重写)override,还是会转去检查父类,最终检查回A类的话,就会直接调用这个virtual方法。

    四.总结

      1.virtual关键字在实现继承的时候使用。

      2.在申明类定义了虚方法,那么它就会去判断实现类是否有重写(override)该方法,并调用之。

      3.延伸知识,在Java中,所有类的方法都是默认virtual。

  • 相关阅读:
    数据库访问表的问题
    UVA 10943全加和(规律)
    POJ 2594 最小路径覆盖 + 传递闭包
    phonegap入门7 capture.captureVideo 录像
    第二部分 Linux Shell高级编程技巧——第二章 Shell工具
    C#写的光模块烧写软件
    关于java的++和操作符,你真的搞明白了吗?
    MFCATL IDispatch调度接口
    c/c++函数调用约定
    HDOJ 2955 Robberies (0/1背包)
  • 原文地址:https://www.cnblogs.com/shadoll/p/14464853.html
Copyright © 2011-2022 走看看