前言:通过这篇文章可以将C#中的虚方法理解透彻,讲的非常详细,十分推荐刚入门的小伙伴收藏嗷!!!

目录:

  • 一、虚方法的概念
  • 二、虚方法的特点
  • 三、虚方法的作用
  • 四、虚方法的声明
  • 五、虚方法的执行
  • 六、虚拟类的规则

一、虚方法的概念

在C#中,虚方法就是可以被子类重写的方法,如果子类重写了虚方法,则在运行时将运行重写的逻辑;如果子类没有重写虚方法,则在运行时将运行父类的逻辑。虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它会根据运行时期对象实例来动态判断要调用的函数,其中那个申明时定义的类叫申明类,那个执行时实例化的类叫实例类。虚方法是用virtual关键字声明的

A a = new B(); 其中A是申明类,B是实例类。

二、虚方法的特点

  1. 虚方法前不允许有static,abstract,或override修饰符
  2. 虚方法不能是私有的(因为在子类中要进行重写),所以不能使用private修饰符
  3. 不能在声明虚方法的同时指定重写虚方法,因为重写方法只能重写基类的虚方法,也就是要提前在基类中声明虚方法,所以virtual关键字和override关键字不能同时使用。

三、虚方法的作用

  1. 允许派生类(即其子类)对父类进行扩展。
  2. 虚方法是多态特性的一种体现。
  3. 增加开发过程中的可维护性,条理清晰明了。

四、虚方法的声明

在父类中:

public virtual 返回类型 方法名()
{方法体;
}

在子类中:

public override 返回值类型 方法名()
{base.父类方法;方法体;
}

五、虚方法的执行

一般方法在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,也就是写死了的!

虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它会根据运行时期对象实例来动态判断要调用的函数。

具体的检查流程如下:

  1. 当调用一个对象的方法时,系统会直接去检查这个对象申明定义的类,即申明类,看所调用的方法是否为虚方法。
  2. 如果不是虚函数,那么它就直接执行该函数。如果有virtual关键字,也就是一个虚方法,那么这个时候它就不会立刻执行该函数了,而是转去检查对象的实例类。
  3. 在这个实例类里,它会检查这个实例类的定义中是否有实现该虚方法(通过new关键字)或是否有重新实现该虚方法(通过override关键字),如果有,那么OK,它就不会再找了,而马上执行该实例类中的这个重新实现的方法。而如果没有的话,系统就会不停地往上找实例类的父类,并对父类重复刚才在实例类里的检查,直到找到第一个重载了该虚方法的父类为止,然后执行该父类里重载后的方法。

下面我们通过具体实例看看:
例1:

 class A{public virtual void Getreturn(){Console.WriteLine("我是A类的虚方法");}}class Program{static void Main(string[] args){A a = new A();//定义一个a这个A类的对象,这个A就是a的申明类,实例化a对象,A是a的实例类a.Getreturn();Console.ReadLine();}}

过程:1.先检查申明类A 2.检查到是Getreturn是虚拟方法 3.转去检查实例类A,结果是它本身 4.执行实例类A中实现Getreturn的方法 5.输出结果我是A类的虚方法

例2:

 class A{public virtual void Getreturn(){Console.WriteLine("我是A类的虚方法");}}class B : A{public override void Getreturn() //重新实现了虚方法 {Console.WriteLine("我是B类重写后的方法");}}class Program{static void Main(string[] args){A a = new B();//定义一个a这个A类的对象,这个A就是a的申明类,实例化a对象,B是a的实例类a.Getreturn();Console.ReadLine();}}

过程:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重写的方法 4.执行实例类B中的方法 5.输出结果我是B类重写后的方法

例3:

 class A{public virtual void Getreturn(){Console.WriteLine("我是A类的虚方法");}}class B : A{public override void Getreturn() //重新实现了虚方法 {Console.WriteLine("我是B类重写后的方法");}}class C : B{}class Program{static void Main(string[] args){A a = new C();//定义一个a这个A类的对象,这个A就是a的申明类,实例化a对象,C是a的实例类a.Getreturn();Console.ReadLine();}}

过程:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重写的方法 4.转去检查类C的父类B,有重写的方法5.执行父类B中的Getreturn方法 6.输出结果我是B类重写后的方法

例4:

 class A{public virtual void Getreturn(){Console.WriteLine("我是A类的虚方法");}}class B : A{public new void Getreturn() //覆盖父类里的同名函数,而不是重新实现  {Console.WriteLine("我是B类New方法");}}class Program{static void Main(string[] args){A a = new B();//定义一个a这个A类的对象,这个A就是a的申明类,实例化a对象,B是a的实例类a.Getreturn();Console.ReadLine();}}

过程:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,无重写的(这个地方要注意了,虽然B里有实现Getreturn(),但没有使用override关键字,所以不会被认为是重写) 4.转去检查类B的父类A,就是它本身 5.执行父类A中的Getreturn方法 6.输出结果我是A类的虚方法

例5:

 class A{public virtual void Getreturn(){Console.WriteLine("我是A类的虚方法");}}class B : A{public new void Getreturn() //覆盖父类里的同名函数,而不是重新实现  {Console.WriteLine("我是B类New方法");}}class Program{static void Main(string[] args){B b = new B();//定义一个b这个B类的对象,这个B就是b的申明类,实例化b对象,B是b的实例类b.Getreturn();Console.ReadLine();}}

过程:1.先检查申明类B 2.检查到不是虚拟方法 3.执行B类里的Getreturn() 4.输出结果我是B类New方法

可以使用抽象方法重写基类中的虚方法

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

密封类可以重写基类中的虚方法(基类中的虚方法将隐式的转化为非虚方法,但密封类本身不能再增加新的虚方法)

 class A{public virtual void Getreturn(){Console.WriteLine("A类的虚方法");}}sealed class Program:A{public override void Getreturn(){Console.WriteLine("Program类重写后的方法");}static void Main(string[] args){Program p = new Program();p.Getreturn();Console.ReadLine();}}

六、虚拟类的规则

  1. 虚拟类其实指的是正常类中的虚拟方法,所以虚拟类可以直接使用实例
  2. 虚拟方法是在方法前加virtual关键字
  3. 虚拟函数与正常函数没有区别
  4. 子类继承虚拟类可以实现虚拟方法也可以不实现虚拟方法。(实现=重写方法)

基类中使用虚方法,在子类中重写的时候,有时想用基类中的方法时,可以使用base关键字调用

C#中base关键字的用法大全

通过阅读这篇文章你收获了不少吧,给博主点波赞吧!有不足之处可以提出来,评论区见!!!!!!!

C#虚方法详解(一切尽有,建议收藏!!!)相关推荐

  1. Unity(C#) 虚方法详解

    目录 一.虚方法是什么 二.虚方法的作用 三.虚方法的实现 一.虚方法是什么 c#中,加上virtual关键字声明的方法即为虚方法. 定义方式如下: 访问修饰符 virtual 返回类型 函数名(参数 ...

  2. ❤️思维导图整理大厂面试高频数组: 两万字详解各种数组求和(建议收藏)❤️

    此专栏文章是对力扣上算法题目各种方法的总结和归纳, 整理出最重要的思路和知识重点并以思维导图形式呈现, 当然也会加上我对导图的详解. 目的是为了更方便快捷的记忆和回忆算法重点(不用每次都重复看题解), ...

  3. ❤️pandas df.loc[] 与 df.iloc[] 详解及其区别,建议收藏❤️

    文章目录 思维导图 一.df.loc[]与df.iloc[]区别 二.df.loc[]详解 df.loc[] 允许输入 三.df.iloc[]详解 df.iloc[] 允许输入 df.loc[]与df ...

  4. 【node节点版本管理器NVM,详解安装教程,建议收藏】

    平常我们在做开发时,可能会用到不同的nodejs版本,如果每次都进行下载安装,就很麻烦了.而nvm刚好帮助我们解决了这一问题. 1.下载nvm nodejs官网:http://nodejs.cn/ n ...

  5. 【SQL】一文详解嵌入式SQL(建议收藏)

  6. [享学Eureka] 三十一、DiscoveryClient透彻解析(八):接口方法和shutdown()方法详解

    成为一个成功者最重要的条件,就是每天精力充沛的努力工作,不虚掷光阴. –> 返回Netflix OSS套件专栏汇总 <– 代码下载地址:https://github.com/f641385 ...

  7. python统计csv行数_对Python 多线程统计所有csv文件的行数方法详解

    如下所示: #统计某文件夹下的所有csv文件的行数(多线程) import threading import csv import os class MyThreadLine(threading.Th ...

  8. python修改文件内容_Python批量修改文本文件内容的方法详解

    这篇文章主要介绍了Python批量修改文本文件内容的方法的相关资料,需要的朋友可以参考下 Python批量替换文件内容,支持嵌套文件夹 import os path="./" fo ...

  9. python二维元组_python中读入二维csv格式的表格方法详解(以元组/列表形式表示)

    如何去读取一个没有表头的二维csv文件(如下图所示)? 并以元组的形式表现数据: ((1.0, 0.0, 3.0, 180.0), (2.0, 0.0, 2.0, 180.0), (3.0, 0.0, ...

最新文章

  1. 机器学习特征表达——日期与时间特征做离散处理(数字到分类的映射),稀疏类分组(相似特征归档),创建虚拟变量(提取新特征) 本质就是要么多变少,或少变多...
  2. switch()中不允许的数据类型有?
  3. 微服务架构(二):融入微服务的企业集成架构
  4. [Leetcode][第336题][JAVA][回文对][暴力][HashSet][字典树]
  5. Hadoop之Flume详解
  6. 评审专家:基金本子“瘦”点好
  7. 如何给自己的个人博客添加一个呆萌的live-2d博客精灵/看板娘
  8. 【JAVA SE】第十三章 序列化与反序列化
  9. qt访问mysql驱动64_64位 Qt5.12 MySql 连接问题
  10. 解决Linux系统在设置alias命令重启后失效的问题
  11. Springboot JpaRepository findOne() 方法报错
  12. c语言 int转bool,C语言的布尔类型(_Bool)【转】
  13. c#调用python的四种方法
  14. 多元梯度下降法演练(1)--特征缩放(特征归一化),Feature Scaling,mean normalization machine learning
  15. PHP ASCII 排序方法
  16. opengl导入obj模型
  17. 微信html页面缓存问题,浅谈微信页面入口文件被缓存解决方案_简单_前端开发者...
  18. 利用计算机打开电视盒子,原来还可以把旧笔记本电脑当电视盒子用!
  19. 服务器挖矿病毒的排查过程
  20. USB学习入门(三)------众里寻他千百度(windows)

热门文章

  1. redis跳跃表实现原理
  2. App测试流程及测试点分享
  3. Object转Map和Map转Object
  4. 蒲公英路由器解决方案
  5. office2016每次打开word都要配置进度的解决方案
  6. 析构函数、虚析构函数、纯虚析构函数
  7. 微信小程序两个view之间有间隙
  8. onBlur事件与onfocus事件 (js)
  9. 爱因斯坦在63岁时说
  10. springboot整合redis实现HyperLogLog统计文章浏览量使用过期策略完成数据库同步