c#中虚函数的相关使用方法
发布时间:2022-10-25 05:44:53
若一个实例方法声明前带有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();
}
}


猜你喜欢
- 最近做了一个MyEclipse项目,但是没开始多久就发现了这个问题:只要文件被修改过,不论多小的修改,保存的时候都会跳出一个框框,里面写着t
- 1、概念首先我们理解一下,什么叫做完美数?问题描述:若一个自然数,它所有的真因子(即除了自身以外的约数)的和恰好等于它本身,这种数叫做完全数
- 一、使用策略枚举来优化if-else看到网上蛮多人推荐使用策略模式来优化if-else,但我总觉得,搞一堆策略类来优化大批量if-else,
- jQuery的方法连缀使用起来非常方便,可以简化语句,让代码变得清晰简洁。那C#的类方法能不能也实现类似的功能呢?基于这样的疑惑,研究了一下
- 关于这三个关键字之前可以研究一下原本的一些操作using System;using System.Collections.Generic;u
- YAMLSpring Boot 提供了大量的自动配置,极大地简化了spring 应用的开发过程,当用户创建了一个 Spring Boot 项
- 本文实例为大家分享了Android使用RecyclerView打造首页轮播图的具体代码,供大家参考,具体内容如下先看看效果图:停在中间自动翻
- 导读 Spring Boot方式的项目开发已经逐步成为Java应用开发领域的主流框架,它不仅可以方便地创建生产级的Spring应用
- 问题描述Feign 在请求时是不会将 request 的请求头带着请求的,导致假如 Feign 调用的接口需要请求头的信息,比如当前用户的
- 使用System.Threading.Thread类可以创建和控制线程。常用的构造函数有: // 摘要: // 初
- Visual Studio 2019 Vue项目 创建成功后可看到如下结构 Visual Studio 2019配置vue项目具体文件结构如
- 以下是app.config或web.config的定义,定义了一个参数,键为Isinit,值为false<?xml version=&
- java 闰年判断前言:给定一个年份,判断这一年是不是闰年。当以下情况之一满足时,这一年是闰年:1. 年份是4的倍数而不是100的倍数;2.
- instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为:boolean result = o
- 导出excel是咱Java开发的必备技能啦,之前项目有这个功能,现在将其独立出来,分享一下。所用技术就是SpringBoot,然后是MVC架
- 不用Spring管理事务?让我们先来看一下不用spring管理事务时,各种框架是如何管理事务的使用JDBC来管理事务使用Hibernate来
- 本文实例为大家分享了java实现通讯录管理系统的具体代码,供大家参考,具体内容如下完成项目的流程:1.根据需求,确定大体方向 2.功能模块分
- 1.一级指针#include?<stdio.h>int?main(){?int?data?=?10;?int?*p1?=?&am
- 本文实例讲述了Android编程实现VideoView循环播放功能的方法。分享给大家供大家参考,具体如下:package com.hangc
- 上次写了一篇博文,但是每次更新图标时,桌面会闪烁(刷新)https://www.jb51.net/article/73350.htm,有博友