C#中的虚函数virtual
简单介绍虚函数virtual
在某基类中声明 virtual 并在一个或多个派生类中被重新定义的成员函数称为虚函数。
虚函数的作用就是实现多态性(Polymorphism),多态性是将接口与实现进行分离。
C#作为完全面向对象语言,所有函数并不默认为virtual,但可以在基类中声明关键字virtual,就可以在其派生类中通过关键字override重写该函数。重写后的virtual函数依旧是virtual函数。由于virtual只对类中的实例函数成员有意义,所以成员字段和静态函数都不能声明为virtual,也不能与override和abstract一起用。
虚函数与一般函数的区别
一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,也就是写死的!而虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它会根据运行时期对象实例来动态判断要调用的函数,其中声明时定义的类叫声明类,执行时实例化的类叫实例类。
使用虚函数virtual
1、当调用一个对象的函数时,系统会直接去检查这个对象声明定义的类,即声明类,看所调用的函数是否为虚函数。
2、如果不是虚函数,那么它就直接执行该函数。而如果有virtual关键字,也就是一个虚函数,那么这个时候它就不会立刻执行该函数了,而是转去检查对象的实例类。
3、在这个实例类里,他会检查这个实例类的定义中是否有重新实现该虚函数(通过override关键字),如果有,则马上执行该实例类中的这个重新实现的函数。而如果没有,系统会不停地往上找实例类的父类,并对父类重复刚才在实例类里的检查,直到找到第一个重载了该虚函数的父类为止,然后执行该父类里重载后的函数。
实例:

运行结果:

常见面试题:
class Program
{
class A
{
public A()
{
PrintFields();
}
public virtual void PrintFields() { }
} class B : A
{
int x = 1;
int y; public B()
{
y = -1;
} public override void PrintFields()
{
Console.WriteLine("x={0},y={1}", x, y);
}
} static void Main(string[] args)
{
new B();
}
}
问:当使用new B()创建B的实例时,产生什么输出?
答:x=1,y=0
解析:创建B的实例,先隐式调用父类A的无参构造函数,执行PrintFields()方法,检查到是虚方法,转去检查实例类B,有重载方法,执行重载方法,输出x=1,y=0
注意:创建子类对象时会首先调用父类的构造函数,然后才会调用子类本身的构造函数,如果没有指明要调用父类的哪一个构造函数,系统会隐式地调用父类的无参构造函数
End!
C#中的虚函数virtual的更多相关文章
- cc38b_demo_C++_异常_(2)txwtech在异常中使用虚函数-多态
//cc38b_demo,21days_C++_异常_(2)txwtech20200121在异常中使用虚函数-多态 //--异常层次结构//*异常的类-创建自己的异常类//*异常派生-就是继承//*异 ...
- C++中的虚函数解析[The explanation for virtual function of CPlusPlus]
1.什么是虚函数? ...
- C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现
tfref 前言 C++对象的内存布局 只有数据成员的对象 没有虚函数的对象 拥有仅一个虚函数的对象 拥有多个虚函数的对象 单继承且本身不存在虚函数的继承类的内存布局 本身不存在虚函数(不严谨)但存在 ...
- 关于在C#中构造函数中调用虚函数的问题
在C#中如果存在类的继承关系,应避免在构造函数中调用虚函数.这是由于C#的运行机制造成的,原因如下: 新建一个类实例时,C#会先初始化该类(对类变量赋值,并将函数记在函数表中),然后再初始化父类.构造 ...
- C++ 构造函数中调用虚函数
我们知道:C++中的多态使得可以根据对象的真实类型(动态类型)调用不同的虚函数.这种调用都是对象已经构建完成的情况.那如果在构造函数中调用虚函数,会怎么样呢? 有这么一段代码: class A { p ...
- C++箴言:避免构造或析构函数中调用虚函数
如果你已经从另外一种语言如C#或者Java转向了C++,你会觉得,避免在类的构造函数或者析构函数中调用虚函数这一原则有点违背直觉.但是在C++中,违反这个原则会给你带来难以预料的后果和无尽的烦恼. 正 ...
- 读书笔记 effective c++ Item 9 绝不要在构造函数或者析构函数中调用虚函数
关于构造函数的一个违反直觉的行为 我会以重复标题开始:你不应该在构造或者析构的过程中调用虚函数,因为这些调用的结果会和你想的不一样.如果你同时是一个java或者c#程序员,那么请着重注意这个条款,因为 ...
- C#中的虚函数及继承关系
转载:http://blog.csdn.net/suncherrydream/article/details/8423991 若一个实例方法声明前带有virtual关键字,那么这个方法就是虚方法. 虚 ...
- C#虚函数virtual详解
在面向对象编程中,有两种截然不同的继承方式:实现继承和接口继承.在实现继承时候,在Java中,所有函数默认都是virtual的,而在C#中所有函数并不默认为virtual的,但可以在基类中通过声明关键 ...
随机推荐
- LNK1104 无法打开文件“xxx.lib”
尝试解决方法: 1.找到这个库,把这个库移动到特定的文件夹下,在属性中添加这个库: 具体来说:打开VS项目->项目属性->配置属性->C/C+±>附加包含目录->编辑-& ...
- vue router 导航守卫生命周期
导航守卫 导航守卫主要用来通过跳转或取消的方式守卫导航.有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的.(记住参数或查询的改变并不会触发进入/离开的导航守卫.你可以通过观察$r ...
- JVM 启动参数,共分为3类
JVM 启动参数,共分为3类: 类别 说明 标准参数(-) 所有的JVM实现都必须实现这些参数的功能,而且向后兼容: 非标准参数(-X) 这些参数不是虚拟机规范规定的.因此,不是所有VM的实现(如:H ...
- linux中以.d结尾的目录
一般为了保持对原有配置方式的兼容,而增加的.d结尾目录. 如: /etc/X11/xorg.conf 这原本是个文件,现在也有了一个/etc/X11/xorg.conf.d这样的目录,显卡驱动的相关设 ...
- <Math> 50 367
50. Pow(x, n) abs (Integer.MIN_VALUE) > Integer.MAX_VALUE class Solution { public double myPow(do ...
- 微信小程序开发工具调试没问题,真机调试Provisional headers are shown
from: https://blog.csdn.net/github_38928905/article/details/83105523 在开发工具调试,请求正常没问题,使用真机调试,请求异常:Pro ...
- mission3--dp
A---母牛的故事 题目大意:第一年有一头母牛,每年年初母牛生小母牛,小母牛第四个年头可以开始生小牛. 问第n年有多少头牛. 题解: (1)列出前几项来找规律(2)第i年牛的数量=第i-1年牛的数量+ ...
- [LeetCode] 875. Koko Eating Bananas 科科吃香蕉
Koko loves to eat bananas. There are N piles of bananas, the i-th pile has piles[i] bananas. The g ...
- JMM与happens-before
happens-before是JMM最核心的概念,理解happens-before是理解JMM的关键. 一.JMM的设计 首先,让我们先分析一下JMM的设计意图.从JMM的设计者的角度,在设计JMM的 ...
- Mysql 生成不重复的随机数字
在网上查找Mysql 生成不重复的随机数字 ,竟然没找到合适的例子. 其实思路很简单,利用MySQL现有的函数,然后进行加工处理,达到预期的结果.可以用到的MySQL函数为rand() ,以及 rou ...