C#虚函数virtual详解

46 篇文章 0 订阅
 在面向对象编程中,有两种截然不同的继承方式: 实现继承和接口继承。在实现继承时候,在Java中,所有函数默认都是virtual的,而在C#中所有函数并不默认为virtual的,但可以在基类中通过声明关键字virtual,就可以在其派生类中通过关键字override重写该函数。

     重写后的virtual函数依旧是virtual函数。由于virtual只对类中的实例函数成员有意义,所以成员字段和静态函数都不能声明为virtual,也不能与override和abstract一起用。C#中可以设置virtual属性、索引器或事件,例如  

  1. virtual string Name  
  2.         {  
  3.             get;  
  4.             set;  
  5.         }   
virtual string Name
        {
            get;
            set;
        } 

无virtual和override关键字“重写”

     如果签名后的函数在基类中都进行了声明,却没有用virtual和override关键字,例如:

  1.    class Base1  
  2.     {  
  3.         public  void printMethod()  
  4.         {  
  5.             Console.WriteLine("base1");  
  6.         }  
  7.     }  
  8.   
  9.     class Derived1 : Base1  
  10.     {  
  11.         public  void printMethod()  
  12.         {  
  13.             Console.WriteLine("derived1");  
  14.         }  
  15.     }  
  16.      class Program  
  17.     {  
  18.         static void Main(string[] args)  
  19.         {  
  20.             Base1 base1 = new Base1();  
  21.             Derived1 derived = new Derived1();  
  22.   
  23.             base1.printMethod();  
  24.             derived.printMethod();  
  25.   
  26.             base1 = new Derived1();  
  27.             base1.printMethod();  
  28.   
  29.   
  30.             Console.ReadLine();  
  31.         }  
  32. }  
   class Base1
    {
        public  void printMethod()
        {
            Console.WriteLine("base1");
        }
    }

    class Derived1 : Base1
    {
        public  void printMethod()
        {
            Console.WriteLine("derived1");
        }
    }
     class Program
    {
        static void Main(string[] args)
        {
            Base1 base1 = new Base1();
            Derived1 derived = new Derived1();

            base1.printMethod();
            derived.printMethod();

            base1 = new Derived1();
            base1.printMethod();


            Console.ReadLine();
        }
}


  1.  输出为:  
 输出为:

          base1

          derived1

          base1

     由于方法相同,在用子类新方法编译代码时候,程序在应该调用哪种方法上就会有潜在的冲突,此时编译器会发出警告,认为子类Derived1的printMethod()隐藏了父类Base1的printMethod();此时可以从新命名子类Derived1的printMethod(),这是最好的解决办法,其次可以通过关键字new隐藏此方法来控制版本。

     这是所谓的无virtual和override的“重写”其实只是隐藏

有virtual和override关键字“重写”

   在派生类中添加关键字virtual和override,实现对基类的重写:

  1. class Base1  
  2.     {  
  3.         public virtual void printMethod()  
  4.         {  
  5.             Console.WriteLine("base1");  
  6.         }  
  7.     }  
  8.   
  9.     class Derived1 : Base1  
  10.     {  
  11.         public  override void printMethod()  
  12.         {  
  13.             Console.WriteLine("derived1");  
  14.         }  
  15.     }  
  16.       
  17.   
  18.     class Program  
  19.     {  
  20.         static void Main(string[] args)  
  21.         {  
  22.             Base1 base1 = new Base1();  
  23.             Derived1 derived = new Derived1();  
  24.   
  25.          
  26.             base1.printMethod();  
  27.             derived.printMethod();  
  28.   
  29.             base1 = new Derived1();  
  30.             base1.printMethod();  
  31.             Console.ReadLine();  
  32.         }  
  33.     }  
class Base1
    {
        public virtual void printMethod()
        {
            Console.WriteLine("base1");
        }
    }

    class Derived1 : Base1
    {
        public  override void printMethod()
        {
            Console.WriteLine("derived1");
        }
    }
    

    class Program
    {
        static void Main(string[] args)
        {
            Base1 base1 = new Base1();
            Derived1 derived = new Derived1();

       
            base1.printMethod();
            derived.printMethod();

            base1 = new Derived1();
            base1.printMethod();
            Console.ReadLine();
        }
    }


 

  1. 此时,输出的结果是:  
此时,输出的结果是:

                      base1

                     derived1

                     derived1

  在类的定义中,申明时定义的类叫申明类,执行实例化时候定义的类叫实例类。例如:

                                    Base1 base1 = new Derived1 ();其中Base1叫做申明类,而Derived1则是实例类。

  此时编译器具体的检查的流程如下

1、当调用函数时,系统会直接去检查申明类,看所调用的函数是否为虚函数;

2、如果不是,那么它就直接执行该函数。如果是virtual函数,则转去检查对象的实例类。

3.在实例类中,若有override的函数,则执行该函数,如果没有,则依次上溯,按照同样步骤对父类进行检查,知道找到第一个override了此函数的父类,然后执行该父类中的函数。(星梦《C#虚函数virtual详解收藏》)

 由此可知,

若子类Derived1中未添加关键字override,则直接在base1中执行父类同名函数,此时输出结果为:

    base1

    derived1

    base1

依次类推,若有Derived2继承了Derived1,即:

  1. class Derived2 : Derived1  
  2.   
  3.  {   
  4.   
  5.     public   void printMethod(){  
  6.   
  7.         Console.WriteLine("derived2");  
  8.   
  9.     }  
  10.   
  11.  }  
   class Derived2 : Derived1

    { 

       public   void printMethod(){

           Console.WriteLine("derived2");

       }

    }


 

在Program类 中执行

  1. base1 = new Derived2();  
  2.   
  3.  base1.printMethod();  
 base1 = new Derived2();

  base1.printMethod();


           

则此时执行的是Derived2中override的同名函数printMethod()。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值