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

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

virtual string Name
{
get;
set;
}
无virtual和override关键字“重写”

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

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();
}
}

输出为:
          base1

derived1

base1

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

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

有virtual和override关键字“重写”

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

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();
}
}

此时,输出的结果是:
                      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,即:

class Derived2 : Derived1

{

public void printMethod(){

Console.WriteLine("derived2");

}

}

在Program类 中执行

base1 = new Derived2();

base1.printMethod();

则此时执行的是Derived2中override的同名函数printMethod()。
---------------------
作者:songsz123
来源:CSDN
原文:https://blog.csdn.net/songsz123/article/details/7369913
版权声明:本文为博主原创文章,转载请附上博文链接!

C#虚函数virtual详解的更多相关文章

  1. C#虚方法virtual详解

    转: http://www.cnblogs.com/jason_yjau/archive/2009/08/25/1553949.html C#虚方法virtual详解 在C++.Java等众多OOP语 ...

  2. 4.C#虚方法virtual详解

    C#虚方法virtual详解 在C++.Java等众多OOP语言里都可以看到virtual的身影,而C#作为一个完全面向对象的语言当然也不例外. 虚拟函数从C#的程序编译的角度来看,它和其它一般的函数 ...

  3. 虚方法virtual详解

    虚方法virtual详解   从C#的程序编译的角度来看,它和其它一般的函数有什么区别呢?一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,也就是写死了的!而虚函数在 ...

  4. C++:虚函数的详解

    5.4.2 虚函数详解 1.虚函数的定义 虚函数就是在基类中被关键字virtual说明,并在派生类重新定义的函数.虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问 ...

  5. 虚方法virtual详解(转载)

    从C#的程序编译的角度来看,它和其它一般的函数有什么区别呢?一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,也就是写死了的!而虚函数在编译期间是不被静态编译的,它的 ...

  6. 【转】C#虚方法virtual详解

    转:https://www.cnblogs.com/zhaoshujie/p/10502404.html 在C++.Java等众多OOP语言里都可以看到virtual的身影,而C#作为一个完全面向对象 ...

  7. C++ 派生类函数重载与虚函数继承详解

    目录 一.作用域与名字查找 1.作用域的嵌套 2.在编译时进行名字查找 3.名字冲突与继承 4.通过作用域运算符来使用隐藏的成员 二.同名函数隐藏与虚函数覆盖 1.几种必须区分的情况 2.一个更复杂的 ...

  8. 自写函数VB6 STUFF函数 和 VB.net 2010 STUFF函数 详解

    '*************************************************************************'**模 块 名:自写函数VB6 STUFF函数 和 ...

  9. SQL Server数据库ROW_NUMBER()函数使用详解

    SQL Server数据库ROW_NUMBER()函数使用详解 摘自:http://database.51cto.com/art/201108/283399.htm SQL Server数据库ROW_ ...

随机推荐

  1. for循环输出素数探究【java】

    一.判断953是不是为素数(质数). 代码: /** 判断953是不是为素数(质数) 分析: 素数指整数在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数. 假设953是素数,则: ...

  2. 菜鸟系列docker——docker镜像下(5)

    1. docker镜像构建 该章节主要介绍2种构建docker镜像的方式.当然,当前基本上需要的基础镜像都有,直接使用即可.例如数据库.中间件之类的,只需要拿来使用即可,但是依然存在需要开发者构建镜像 ...

  3. 完整例子-正则控制input的输入

    转 : https://www.cnblogs.com/ckf1988/p/5619337.html

  4. Django 系列博客(三)

    Django 系列博客(三) 前言 本篇博客介绍 django 的前后端交互及如何处理 get 请求和 post 请求. get 请求 get请求是单纯的请求一个页面资源,一般不建议进行账号信息的传输 ...

  5. 在Object-C中学习数据结构与算法之排序算法

    笔者在学习数据结构与算法时,尝试着将排序算法以动画的形式呈现出来更加方便理解记忆,本文配合Demo 在Object-C中学习数据结构与算法之排序算法阅读更佳. 目录 选择排序 冒泡排序 插入排序 快速 ...

  6. 【转载】 PhpStudy修改Apache的端口号

    phpStudy是一个PHP调试环境的程序集成包.该程序包集成最新的Apache+PHP+MySQL+phpMyAdmin+ZendOptimizer,一次性安装,无须配置即可使用,是非常方便.好用的 ...

  7. Layui table 组件的使用:初始化加载数据、数据刷新表格、传参数

    背景 笔者之前一直使用 bootstrap table ,因为当前项目中主要使用 Layui 框架,于是也就随了 Layui table ,只是在使用的时候出现了一些问题,当然也是怪自己不熟悉的锅吧! ...

  8. C#通过调用WinApi打印PDF文档类,服务器PDF打印、IIS PDF打印

    其他网站下载来的类,可以用于Winform.Asp.Net,用于服务器端PDF或其他文件打印. 直接上代码: using System; using System.Collections.Generi ...

  9. JavaScript 图片弹框显示

    function fnCreate(src) {             /* 要创建的div的classname */             var ClassName = "thumb ...

  10. [PHP] PHP在CLI环境下的错误日志

    1.display_errors = Off;//控制php是否输出错误;在生产环境中输出会泄露敏感信息;建议记录错误而不是将它们发送到STDOUToff :不显示任何错误;stderr :向STDE ...