C#中的虚方法

当类中的方法声明前加上virtual, 该方法称为虚方法,虚方法可以被重载。

如果对方法使用了virtual修饰符后,将不再允许有static,abstract或override修饰符对方法进行定义。

对于非虚方法,无论被其所在类的实例还是其所在类的继承类的实例调用执行方式不变。
而对于虚方法,执行方式可以被派生类改变。这种改变可以通过方法的重载来实现。

当调用虚方法时,运行时将确定调用对象是什么类的实例。同时调用适当的覆盖方法,通过override关键字来覆盖。

//转自百度知道
virtual 用在基类中,指定一个虚方法(属性),表示这个方法(属性)可以重写。
override 用在派生类中,表示对基类虚方法(属性)的重写。
以上的基类和派生类都是相对的。B 是 C 的基类,也可以是 A 的派生类,B 中既可以对 A 中的 virtual 虚方法用 override 重写,也可以指定 virtual 虚方法供 C 重写。

不能重写非虚方法或静态方法。
重写的基方法必须是 virtual、abstract 或 override 的。为什么 override 也可以重写呢?因为基类中的 override 实际上是对基类的基类进行的重写,由于继承可传递,所以也可以对基类中 override 的方法进行重写。
override 声明不能更改 virtual 方法的可访问性。override 方法和 virtual 方法必须具有相同的访问级别修饰符。
不能使用修饰符 new、static、virtual 或 abstract 来修改 override 方法。

重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且被重写的属性必须是 virtual、abstract 或 override 的。


虚函数从C#的程序编译的角度来看,它和其它一般的函数有什么区别呢?一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,也就是写死了的!而虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它会根据运行时期对象实例来动态判断要调用的函数,其中那个申明时定义的类叫申明类,那个执行时实例化的类叫实例类。 如:飞禽 bird = new 麻雀(); 
那么飞禽就是申明类,麻雀是实例类。 具体的检查的流程如下 
1、当调用一个对象的函数时,系统会直接去检查这个对象申明定义的类,即申明类,看所调用的函数是否为虚函数; 
2、如果不是虚函数,那么它就直接执行该函数。而如果有virtual关键字,也就是一个虚函数,那么这个时候它就不会立刻执行该函数了,而是转去检查对象的实例类。 

3、在这个实例类里,他会检查这个实例类的定义中是否有重新实现该虚函数(通过override关键字),如果是有,那么OK,它就不会再找了,而马上执行该实例类中的这个重新实现的函数。而如果没有的话,系统就会不停地往上找实例类的父类,并对父类重复刚才在实例类里的检查,直到找到第一个重载了该虚函数的父类为止,然后执行该父类里重载后的函数。

### C#虚方法与抽象方法的区别 #### 定义方式 在 C# 中,虚方法通过 `virtual` 关键字定义,在基中提供了一个默认实现。而抽象方法使用 `abstract` 关键字标记,位于抽象内,并不给出具体实现[^1]。 ```csharp public class BaseVirtual { public virtual void ShowMessage() { Console.WriteLine("Base Virtual Message"); } } public abstract class BaseAbstract { public abstract void ShowMessage(); } ``` #### 实现要求 对于继承自含有虚方法来说,子可以选择是否重写该方法。然而,当一个继承了带有抽象方法的抽象时,除非这个子本身也是抽象,否则它必须实现所有的抽象方法[^2]。 ```csharp // 继承并选择性覆盖虚方法 public class ChildOfVirtual : BaseVirtual { // 可以省略此部分,默认调用父级版本 public override void ShowMessage() { Console.WriteLine("Child Override Virtual Message"); } } // 必须实现抽象方法 public class ChildOfAbstract : BaseAbstract { public override void ShowMessage() { Console.WriteLine("Implement Abstract Method Here"); } } ``` #### 默认行为差异 由于虚方法已经包含了具体的执行逻辑,因此即使未被任何后代所改写也能正常工作;相反地,因为抽象方法缺乏实际操作内容,所以无法直接实例化其所在的或调用这些未经填补的方法体[^3]。 #### 设计意图对比 - **虚方法**适合于那些希望给定某种基础功能但又允许后续扩展的情况; - **抽象方法**更适用于框架搭建者想要规定某些契约性的接口却不想限定其实现细节的情形下[^4]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值