c#中虚函数的相关使用方法

 更新时间:2013年02月25日 09:27:18   作者:  
若一个实例方法声明前带有virtual关键字,那么这个方法就是虚方法。

若一个实例方法声明前带有virtual关键字,那么这个方法就是虚方法。

虚方法与非虚方法的最大不同是,虚方法的实现可以由派生类所取代,这种取代是通过方法的重写实现的(以后再讲)
虚方法的特点:
虚方法前不允许有static,abstract,或override修饰符
虚方法不能是私有的,因此不能使用private修饰符
虚方法的执行:
我们知道一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,
而虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它会根据运行时期对象实例来动态判断要调用的函数,
其中那个申明时定义的类叫申明类,那个执行时实例化的类叫实例类。
如:A a =new B(); 其中A是申明类,B是实例类。
1.当调用一个对象的函数时,系统会直接去检查这个对象申明定义的类,即申明类,看所调用的函数是否为虚函数;
2.如果不是虚函数,那么它就直接执行该函数。而如果是一个虚函数,那么这个时候它就不会立刻执行该函数了,而是开始检查对象的实例类。
3.在这个实例类里,他会检查这个实例类的定义中是否有实现该虚函数或者重新实现该虚函数(通过override关键字)的方法,
如果有,它就不会再找了,而是马上执行该实例类中实现的虚函数的方法。而如果没有的话,系统就会不停地往上找实例类的父类,
并对父类重复刚才在实例类里的检查,直到找到第一个重载了该虚函数的父类为止,然后执行该父类里重载后的函数。
例1:

复制代码 代码如下:

class A
    {
        publicvirtualvoid Sum()
        {
            Console.WriteLine("I am A Class,I am virtual sum().");
        }
    }
    class Program
    {
        staticvoid Main(string[] args)
        {
             A a=new A();   // 定义一个a这个A类的对象.这个A就是a的申明类,实例化a对象,A是a的实例类  
             a.Sum();
             Console.Read();
        }
    }

 执行a.Sum:
1.先检查申明类A 2.检查到是sum是虚拟方法 3.转去检查实例类A,结果是题本身
4.执行实例类A中实现Sum的方法 5.输出结果 I am A Class,I am virtual sum().
例2:

复制代码 代码如下:

class A
    {
        publicvirtualvoid Sum()
        {
            Console.WriteLine("I am A Class,I am virtual sum().");
        }
    }
    class B : A   
    {
        publicoverridevoid Sum() // 重新实现了虚函数  
        {
            Console.WriteLine("I am B Class,I am override sum().");
        } 

    }
    class Program
    {
        staticvoid Main(string[] args)
        {
             A a=new B();  // 定义一个a这个A类的对象.这个A就是a的申明类,实例化a对象,B是a的实例类             
             a.Sum();
             Console.Read();
        }
    }


执行a.Sum:
1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重写的方法 4.执行实例类B中的方法 5.输出结果 I am B Class,I am override sum().
例3:
复制代码 代码如下:

class A
    {
        publicvirtualvoid Sum()
        {
            Console.WriteLine("I am A Class,I am virtual sum().");
        }
    }
    class B : A   
    {
        publicoverridevoid Sum() // 重新实现了虚函数  
        {
            Console.WriteLine("I am B Class,I am override sum().");
        } 

    }
    class C : B
    {

    }
    class Program
    {
        staticvoid Main(string[] args)
        {
             A a=new C();// 定义一个a这个A类的对象.这个A就是a的申明类,实例化a对象,C是a的实例类             
             a.Sum();
             Console.Read();
        }
    }


执行a.Sum:
1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重写的方法 4.转去检查类C的父类B,有重写的方法
5.执行父类B中的Sum方法 6.输出结果 I am B Class,I am override sum(). 
例4:

复制代码 代码如下:

class A
    {
        publicvirtualvoid Sum()
        {
            Console.WriteLine("I am A Class,I am virtual sum().");
        }
    }
    class B : A   
    {
        publicnewvoid Sum() //覆盖父类里的同名函数,而不是重新实现 
        {
            Console.WriteLine("I am B Class,I am new sum().");
        } 

    }
    class Program
    {
        staticvoid Main(string[] args)
        {
             A a=new B();
             a.Sum();
             Console.Read();
        }
    }


执行a.Sum:
1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,无重写的(这个地方要注意了,虽然B里有实现Sum(),但没有使用override关键字,所以不会被认为是重写) 4.转去检查类B的父类A,就为本身 5.执行父类A中的Sum方法 6.输出结果 I am A Class,I am virtual sum(). 
那么如果在例4里,申明的是类B呢?
复制代码 代码如下:

class A
    {
        publicvirtualvoid Sum()
        {
            Console.WriteLine("I am A Class,I am virtual sum().");
        }
    }
    class B : A   
    {
        publicnewvoid Sum() //覆盖父类里的同名函数,而不是重新实现 
        {
            Console.WriteLine("I am B Class,I am new sum().");
        } 

    }
    class Program
    {
        staticvoid Main(string[] args)
        {
             B b=new B();
             b.Sum();
             Console.Read();
        }
    }


执行B类里的Sum(),输出结果I am B Class,I am new sum().
可以使用抽象函数重写基类中的虚函数吗?
答案是可以的。

复制代码 代码如下:

class A
    {
        publicvirtualvoid PrintFriends()
        {
            Console.WriteLine("A.PrintFriends()");  
        } 
    }
    abstractclass B : A   
    {
        public abstract override void PrintFriends();   //使用override 修饰符,表示抽象重写了基类中该函数的实现
    }
    abstract class C : A
    {
        public abstract new void PrintFriends();        //使用 new 修饰符显式声明,表示隐藏了基类中该函数的实现
    }

密封类可以有虚函数吗?
可以,基类中的虚函数将隐式的转化为非虚函数,但密封类本身不能再增加新的虚函数

复制代码 代码如下:

class A
    {
        publicvirtualvoid Fun()
        {
            Console.WriteLine("I am A.");
        }
    }
    sealedclass Program:A
    {
        public override void Fun()
        {
            Console.WriteLine("I am B.");
        }
        staticvoid Main(string[] args)
        {
            Program p =new Program();
            p.Fun();
            Console.Read();
        }
    }

相关文章

  • CDMA 猫用AT命令发中文短信(C#)

    CDMA 猫用AT命令发中文短信(C#)

    CDMA猫连PDU都不支持,只能发文本短信。而且发中文短信居然是UNICODE,无法在超级终端里输入。只能写程序。网上这个问题谈论地比较多,做起来比较累,还偶尔会出乱码。还是将C#的成功代码帖一下吧。
    2009-08-08
  • C#部署数据库及IIS站点

    C#部署数据库及IIS站点

    这篇文章主要为大家详细介绍了C#部署数据库及IIS站点的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • C#内存管理CLR深入讲解(上篇)

    C#内存管理CLR深入讲解(上篇)

    本文详细讲解了C#内存管理CLR的程序集和应用程序域,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-01-01
  • C#位运算以及实例计算详解

    C#位运算以及实例计算详解

    这篇文章主要给大家介绍了关于C#位运算以及实例计算的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C#具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-07-07
  • 解析C#中的常量及如何在C#编程中定义常量

    解析C#中的常量及如何在C#编程中定义常量

    这篇文章主要介绍了C#中的常量及如何在C#编程中定义常量,是C#入门学习中的基础知识,需要的朋友可以参考下
    2016-01-01
  • 详解c# 中的DateTime

    详解c# 中的DateTime

    这篇文章主要介绍了c# 中的DateTime的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • C# 基础入门--关键字

    C# 基础入门--关键字

    本文主要介绍了C# 基础知识--关键字的相关知识,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-03-03
  • 浅谈C#中ListView类的用法

    浅谈C#中ListView类的用法

    这篇文章主要介绍了浅谈C#中ListView的用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • C#检查指定对象是否存在于ArrayList集合中的方法

    C#检查指定对象是否存在于ArrayList集合中的方法

    这篇文章主要介绍了C#检查指定对象是否存在于ArrayList集合中的方法,涉及C#中Contains方法的使用技巧,需要的朋友可以参考下
    2015-04-04
  • C# Socket实现简单控制台案例

    C# Socket实现简单控制台案例

    这篇文章主要为大家分享了C# Socket简单的控制台案例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05

最新评论