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

若一个实例方法声明前带有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();
        }
    }

(0)

相关推荐

  • C#虚方法的声明和使用实例教程

    本文以实例形式演示了C#虚方法的声明与使用.实例内容主要包括:演示虚方法的声明和使用,定义虚方法进而求几何面积,用虚方法求原始图形的面积.正方形的面积.等边三角形的面积.圆形的面积等. 实现代码如下: using System; public class Graph { protected double ParaVal; protected double pi = 3.1415926; public Graph ( double Para ) { ParaVal = Para; } //定义虚方

  • C#中的高阶函数介绍

    介绍 我们都知道函数是程序中的基本模块,代码段.那高阶函数呢?听起来很好理解吧,就是函数的高阶(级)版本.它怎么高阶了呢?我们来看下它的基本定义: 1:函数自身接受一个或多个函数作为输入 2:函数自身能输出一个函数.  //函数生产函数   满足其中一个就可以称为高阶函数.高阶函数在函数式编程中大量应用.c#在3.0推出Lambda表达式后,也开始慢慢使用了.   目录 1:接受函数 2:输出函数 3:Currying(科里化) 一.接受函数 为了方便理解,都用了自定义. 代码中TakeWhil

  • C#中抽象方法与虚拟方法的区别

    学过C#的人应该都知道抽象方法与虚拟方法,而很多初学者对二者之间的区别并不是很了解.今天本文就来分析一下二者之间的区别.并附上实例加以说明.具体分析如下: 一.主要区别: 对于抽象方法,子类必须实现它. 对于虚拟方法,子类可以重写也可以不重写. 因此,两者约束不同 二.实例代码如下: /* 声明一个抽象类 * 1.抽象类中可以包含变量 * 2.抽象方法中无法声明方法体 */ abstract class AbsClass { string name; public abstract void D

  • C#虚函数用法实例分析

    本文实例讲述了C#虚函数用法.分享给大家供大家参考.具体如下: using System; namespace Test2 { class Plane { public double TopSpeed() { return 300.0D; } } class Jet : Plane { public double TopSpeed() { return 900.0D; } } class Airport { static void Main(string[] args) { Plane plan

  • C#实现向函数传递不定参数的方法

    本文实例讲述了C#实现向函数传递不定参数的方法.分享给大家供大家参考.具体实现方法如下: using System; class Min{ public int MinVla(params int [] nums){ int m; if (nums.Length == 0){ Console.WriteLine("Error: no arguments."); return 0; } m = nums[0]; foreach ( int val in nums){ if ( val &

  • C#中函数的创建和闭包的理解

    动态创建函数 大多数同学,都或多或少的使用过.回顾下c#中动态创建函数的进化: C# 1.0中: 复制代码 代码如下: public delegate string DynamicFunction(string name);   public static DynamicFunction GetDynamicFunction()   {       return GetName;   }   static string GetName(string name)   {       return

  • C#静态构造函数用法实例分析

    本文实例讲述了C#静态构造函数用法.分享给大家供大家参考.具体如下: 当我们想初始化一些静态变量的时候,就需要用到静态构造函数了.这个静态构造函数属于类,而不属于实例,就是说这个构造函数只会被执行一次,即:在创建第一个实例或引用任何静态成员之前,由.NET自动调用. 现在碰到这样一个场景:提供一个静态方法,这个静态方法在不同的地方使用,涉及到一个参数值不同,而其他内容都完全一致.如果是将静态方法的内容复制出来做成另外一个方法,代码冗余太多,做法不可取.使用静态构造函数处理静态变量,则可以尽最大程

  • C#中异步回调函数用法实例

    本文实例讲述了C#中异步回调函数用法.分享给大家供大家参考.具体如下: static void Main(string[] args) { Func<string,string> showMessage = ShowMessage; //设置了回调函数Completed,不能有返回值 IAsyncResult result = showMessage.BeginInvoke("测试异步委托",new AsyncCallback(Completed),null); //半段异

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

    若一个实例方法声明前带有virtual关键字,那么这个方法就是虚方法. 虚方法与非虚方法的最大不同是,虚方法的实现可以由派生类所取代,这种取代是通过方法的重写实现的(以后再讲)虚方法的特点:虚方法前不允许有static,abstract,或override修饰符虚方法不能是私有的,因此不能使用private修饰符虚方法的执行:我们知道一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,而虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它会根据运行时期对象

  • C++中的多态与虚函数的内部实现方法

    1.什么是多态 多态性可以简单概括为"一个接口,多种行为". 也就是说,向不同的对象发送同一个消息, 不同的对象在接收时会产生不同的行为(即方法).也就是说,每个对象可以用自己的方式去响应共同的消息.所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数.这是一种泛型技术,即用相同的代码实现不同的动作.这体现了面向对象编程的优越性. 多态分为两种: (1)编译时多态:主要通过函数的重载和模板来实现. (2)运行时多态:主要通过虚函数来实现. 2.几个相关概念 (1)覆盖.

  • C++中虚函数与纯虚函数的用法

    本文较为深入的分析了C++中虚函数与纯虚函数的用法,对于学习和掌握面向对象程序设计来说是至关重要的.具体内容如下: 首先,面向对象程序设计(object-oriented programming)的核心思想是数据抽象.继承.动态绑定.通过数据抽象,可以使类的接口与实现分离,使用继承,可以更容易地定义与其他类相似但不完全相同的新类,使用动态绑定,可以在一定程度上忽略相似类的区别,而以统一的方式使用它们的对象. 虚函数的作用是实现多态性(Polymorphism),多态性是将接口与实现进行分离,采用

  • mysql中find_in_set函数的基本使用方法

    前言 这是我最近新接触到的一个函数, 我在项目中的使用场景是这样的: 有一个应用类型表,表中有parentId字段和parentIds字段,前者为父级id,后者为多级父级id,在库中都是varchar类型,parentIds由多个父级id拼接而成由","分隔. 组长告知我可以使用该函数,就去进行了了解与使用. 语法 FIND_IN_SET(str,strlist) 定义 假如字符串str在由多个子链组成的字符串列表strlist中,则返回值的范围在1到N之间. 一个字符串列表就是一个由

  • 详解 MySQL中count函数的正确使用方法

    1. 描述 在MySQL中,当我们需要获取某张表中的总行数时,一般会选择使用下面的语句 select count(*) from table; 其实count函数中除了*还可以放其他参数,比如常数.主键id.字段,那么它们有什么区别?各自效率如何?我们应该使用哪种方式来获取表的行数呢? 当搞清楚count函数的运行原理后,相信上面几个问题的答案就会了然于胸. 2. 表结构 为了解决上述的问题,我创建了一张 user 表,它有两个字段:主键id和name,后者可以为null,建表语句如下. CRE

  • c++ 虚函数,虚表相关总结

    面向对象,从单一的类开始说起. class A { private:     int m_a;     int m_b; }; 这个类中有两个成员变量,都是int类型,所以这个类在内存中占用多大的内存空间呢? sizeof(A), 8个字节,一个int占用四个字节.下图验证: 这两个数据在内存中是怎样排列的呢? 原来是这样,我们根据debug出来的地址画出a对象在内存的结构图 如果 class A 中包含成员函数呢? A 的大小又是多少? class A { public:     void f

  • PHP中filter函数校验数据的方法详解

    介绍PHP中filter函数校验数据的方法详解,PHP过滤器包含两种类型:Validation用来验证验证项是否合法 .Sanitization用来格式化被验证的项目,因此它可能会修改验证项的值,将不合法的字符删除. input_filters_list() 用来列出当前系统所支持的所有过滤器. 复制代码 代码如下: <?php foreach(filter_list() as $id => $filter) {     echo $filter.' '.filter_id($filter).

  • 浅谈C++中虚函数实现原理揭秘

    编译器到底做了什么实现的虚函数的晚绑定呢?我们来探个究竟. 编译器对每个包含虚函数的类创建一个表(称为V TA B L E).在V TA B L E中,编译器放置特定类的虚函数地址.在每个带有虚函数的类 中,编译器秘密地置一指针,称为v p o i n t e r(缩写为V P T R),指向这个对象的V TA B L E.通过基类指针做虚函数调 用时(也就是做多态调用时),编译器静态地插入取得这个V P T R,并在V TA B L E表中查找函数地址的代码,这样就能调用正确的函数使晚捆绑发生

  • 在python中bool函数的取值方法

    bool是Boolean的缩写,只有真(True)和假(False)两种取值 bool函数只有一个参数,并根据这个参数的值返回真或者假. 1.当对数字使用bool函数时,0返回假(False),任何其他值都返回真. >>> bool(0) False >>> bool(1) True >>> bool(-1) True >>> bool(21334) True 2.当对字符串使用bool函数时,对于没有值的字符串(也就是None或者空

  • PHP5中虚函数的实现方法分享

    请看下面的代码: 复制代码 代码如下: <?php class A { public function x() { echo "A::x() was called.\n"; } public function y() { self::x(); echo "A::y() was called.\n"; } public function z() { $this->x(); echo "A::z() was called.\n"; } }

随机推荐