C#虚函数virtual详解
在面向对象编程中,有两种截然不同的继承方式:实现继承和接口继承。在实现继承时候,在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详解的更多相关文章
- C#虚方法virtual详解
转: http://www.cnblogs.com/jason_yjau/archive/2009/08/25/1553949.html C#虚方法virtual详解 在C++.Java等众多OOP语 ...
- 4.C#虚方法virtual详解
C#虚方法virtual详解 在C++.Java等众多OOP语言里都可以看到virtual的身影,而C#作为一个完全面向对象的语言当然也不例外. 虚拟函数从C#的程序编译的角度来看,它和其它一般的函数 ...
- 虚方法virtual详解
虚方法virtual详解 从C#的程序编译的角度来看,它和其它一般的函数有什么区别呢?一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,也就是写死了的!而虚函数在 ...
- C++:虚函数的详解
5.4.2 虚函数详解 1.虚函数的定义 虚函数就是在基类中被关键字virtual说明,并在派生类重新定义的函数.虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问 ...
- 虚方法virtual详解(转载)
从C#的程序编译的角度来看,它和其它一般的函数有什么区别呢?一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,也就是写死了的!而虚函数在编译期间是不被静态编译的,它的 ...
- 【转】C#虚方法virtual详解
转:https://www.cnblogs.com/zhaoshujie/p/10502404.html 在C++.Java等众多OOP语言里都可以看到virtual的身影,而C#作为一个完全面向对象 ...
- C++ 派生类函数重载与虚函数继承详解
目录 一.作用域与名字查找 1.作用域的嵌套 2.在编译时进行名字查找 3.名字冲突与继承 4.通过作用域运算符来使用隐藏的成员 二.同名函数隐藏与虚函数覆盖 1.几种必须区分的情况 2.一个更复杂的 ...
- 自写函数VB6 STUFF函数 和 VB.net 2010 STUFF函数 详解
'*************************************************************************'**模 块 名:自写函数VB6 STUFF函数 和 ...
- SQL Server数据库ROW_NUMBER()函数使用详解
SQL Server数据库ROW_NUMBER()函数使用详解 摘自:http://database.51cto.com/art/201108/283399.htm SQL Server数据库ROW_ ...
随机推荐
- for循环输出素数探究【java】
一.判断953是不是为素数(质数). 代码: /** 判断953是不是为素数(质数) 分析: 素数指整数在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数. 假设953是素数,则: ...
- Deep learning with Python 学习笔记(11)
总结 机器学习(machine learning)是人工智能的一个特殊子领域,其目标是仅靠观察训练数据来自动开发程序[即模型(model)].将数据转换为程序的这个过程叫作学习(learning) 深 ...
- mybatis逆向工程(MyBatis Generator)
mybatis逆向工程(MyBatis Generator) 1. 什么是mybatis逆向工程 mybatis官方为了提高开发效率,提高自动对单表生成sql,包括 :mapper.xml.mappe ...
- oracle listener.ora文件配置
# listener.ora Network Configuration File: /oracleDB/product//db_1/network/admin/listener.ora # Gene ...
- Android Studio 使用Menu
首先在res目录下创建一个文件夹名字随意 在对创建的文件夹下在创建一个菜单 名字随意 参看布局 可以看到你的菜单 可以选择添加是么样的菜单 接着要到主活动中重写 onCreateOptionsMenu ...
- Postman Post请求上传文件
Postman Post请求上传文件一.选择post请求方式,输入请求地址 二.填写Headers Key:Content-Type :Value:multipart/form-data 如下图 三. ...
- C#设计模式之七桥接模式(Bridge Pattern)【结构型】
一.引言 今天我们要讲[结构型]设计模式的第二个模式,该模式是[桥接模式],也有叫[桥模式]的,英文名称:Bridge Pattern.大家第一次看到这个名称会想到什么呢?我第一次看到这个模式根据名称 ...
- eclipse安装阿里编码规约插件
点击帮助,Install New Software... 地址为https://p3c.alibaba.com/plugin/eclipse/update 然后选择安装, 一路next即可
- springboot之scheduled任务调度
springboot整合Scheduled可以方便的进行任务调度,话不多说,直接上代码 package com.rookie.bigdata; import org.springframework.b ...
- js/es6 元素拖动
元素事件:鼠标按下事件/鼠标移动事件/鼠标松开事件 元素样式:让元素脱离文档流,采用绝对定位的方式. 一.鼠标按下事件 当鼠标在元素上面按下时,保存元素的初始偏移量和鼠标按下时的坐标,然后在状态变量里 ...