C# 关键字--virtual(转)
C# 关键字--virtual
一、
虚方法或者虚属性并不等同于抽象方法、抽象属性。抽象方法和抽象属性无法直接调用,必须通过派生类进行实现之后才能调用;而虚方法和虚属性是表示在派生类中有可能进行重写的,但是如果没有重写,那么将调用父类中的该虚方法和虚属性。调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。
默认情况下,方法是非虚拟的,不能重写非虚方法(除非使用new关键字)。virtual
修饰符不能与static、abstract、private 或
override
修饰符一起使用。除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。注意:
①在静态属性上使用 virtual 修饰符是错误的。
②通过包括使用 override
修饰符的属性声明,可在派生类中重写虚拟继承属性。
虚拟方法
若一个实例方法的声明中含有 virtual
修饰符,则称该方法为虚拟方法。若其中没有 virtual
修饰符,则称该方法为非虚拟方法。非虚拟方法的实现是不会变的:无论是在声明它的类的实例上调用该方法还是在派生类的实例上调用,实现都是相同的。与此相反,一个虚拟方法的实现可以由派生类取代。取代所继承的虚拟方法的实现的过程称为重写该方法。
class
A
{
public void F() {
Console.WriteLine("A.F"); }
public virtual void
G() { Console.WriteLine("A.G"); }
}
class B:
A
{
new
public void F() {
Console.WriteLine("B.F"); }
public override void G() {
Console.WriteLine("B.G"); }
}
class Test
{
static void Main()
{
B b = new
B();
A ab = b;//这里a的类型是B类对象
A a = new A();
a.F(); //打印A.F
b.F(); //打印B.F
ab.F(); //打印A.F
a.G(); //打印B.G
b.G(); //打印B.G
ab.G(); //打印B.G
}
}
注意:从a.F()与ab.G()返回的结果可以看出,利用new和override关键字对方法进行重写是有区别的。
- 基类对象调用基类对应的方法,不管是否是虚拟方法。
- 派生类对象分两种情况
①引用声明为派生类变量:调用派生类的方法
②引用声明为基类变量:
■如果利用override重写,那么调用派生类中的重写之后的方法。
■如果利用new重写,那么调用基类方法。
注意:上述原则对虚拟属性同样适用!
{
public virtual void Func() // 注意virtual,表明这是一个虚拟函数
{
Console.WriteLine("Func In A");
}
}
class B : A // 注意B是从A类继承,所以A是父类,B是子类
{
public override void Func() // 注意override ,表明重新实现了虚函数
{
Console.WriteLine("Func In B");
}
}
class C : B // 注意C是从B类继承,所以B是父类,C是子类
{
}
class D : A // 注意D是从A类继承,所以A是父类,D是子类
{
public new void Func() // 注意new ,表明覆盖父类里的同名类,而不是重新实现
{
Console.WriteLine("Func In D");
}
}
class Program
{
static void Main(string[] args)
{
A a; // 定义一个a这个A类的对象.这个A就是a的申明类
A b; // 定义一个b这个A类的对象.这个A就是b的申明类
A c; // 定义一个c这个A类的对象.这个A就是c的申明类
A d; // 定义一个d这个A类的对象.这个A就是d的申明类
a = new A(); // 实例化a对象,A是a的实例类
b = new B(); // 实例化b对象,B是b的实例类
c = new C(); // 实例化c对象,C是c的实例类
d = new D(); // 实例化d对象,D是d的实例类
a.Func(); // 执行a.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类A,就为本身 4.执行实例类A中的方法 5.输出结果 Func In A
b.Func(); // 执行b.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重载的 4.执行实例类B中的方法 5.输出结果 Func In B
c.Func(); // 执行c.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重载的 4.转去检查类C的父类B,有重载的 5.执行父类B中的Func方法 5.输出结果 Func In B
d.Func();
// 执行d.Func:1.先检查申明类A 2.检查到是虚拟方法
3.转去检查实例类D,无重载的(这个地方要注意了,虽然D里有实现Func(),但没有使用override关键字,所以不会被认为是重载)
4.转去检查类D的父类A,就为本身 5.执行父类A中的Func方法 5.输出结果 Func In A
D d1 = new D();
d1.Func(); // 执行D类里的Func(),输出结果 Func In D
Console.ReadLine();
}
}
C# 关键字--virtual(转)的更多相关文章
- 关键字 virtual
Virtual是C++ OO机制中很重要的一个关键字.只要是学过C++的人都知道在类Base中加了Virtual关键字的函数就是虚拟函数(例如函数print),于是在Base的派生类Derived中就 ...
- 基础知识系列☞关键字→virtual
看到自己以前的一篇博客,感觉还差点什么,√,代码... using System; namespace Test { public class Program { private static voi ...
- C# 关键字 virtual、override和new的用法
代码如下: class A { public void foo() { Console.WriteLine("A::foo()"); } public virtual void b ...
- virtual关键字
出于多态的考虑,为了覆盖, 子类同名覆盖函数(函数名.参数.返回值都相同) virtual void print(): 这也许会使人联想到函数的重载,但稍加对比就会发现两者是完全不同的:(1)重载的几 ...
- C# 关键字【转】
C#中的关键字 关键字是对编译器具有特殊意义的预定义保留标识符.它们不能在程序中用作标识符,除非它们有一个 @ 前缀.例如,@if 是有效的标识符,但 if 不是,因为 if 是关键字. 下面是列 ...
- C#基础知识系列七(base、this、new、override、abstract、virtual、static)
前言 本文主要来讲解一下C#中,自己觉得掌握的不怎么样或者用的不多,不太熟悉的关键字,主要包括base.this.new.override.abstract.virtual以及针对static字段和s ...
- 基础知识系列☞Abstract和Virtual→及相关知识
转载地址→http://www.cnblogs.com/blsong/archive/2010/08/12/1798064.html 在C#的学习中,容易混淆virtual方法和abstract方法的 ...
- C++ Virtual详解
转自:http://www.cnblogs.com/xd502djj/archive/2010/09/22/1832912.html Virtual是C++ OO机制中很重要的一个关键字.只要是学过C ...
- C++ Virtual介绍 分类: C/C++ 2015-06-16 21:36 26人阅读 评论(0) 收藏
参考链接:http://www.cnblogs.com/xd502djj/archive/2010/09/22/1832912.html 学过C++的人都知道在类Base中加了Virtual关键字的函 ...
随机推荐
- 【转】qlv文件如何转换成mp4 怎样把下载好的qlv格式视频转换成MP4格式
狸窝 复制 收藏 保存到桌面 快速找教程方案 反馈需求 社会主义核心价值观 客服QQ41442901 马上注册 升级VIP 对于视频文件之间的转换问题,我也已经是无力吐槽了,每个 ...
- LVS集群之工作原理和调度算法(2)
LVS的工作机制 LVS里Director本身不响应请求,只是接受转发请求到后方,Realservers才是后台真正响应请求. LVS 工作原理基本类似DNAT,又不完全相像,它是一种四层交换,默 ...
- web.xml解析
常用元素及含义 <!-- standalone 定义了外部定义的 DTD 文件的存在性,有效值是 yes和 no --> <?xml version="1.0" ...
- 应用服务器GC回收常见问题总结
近一段时间多次发现因GC问题造成系统性能问题(应用服务间歇性响应缓慢.应用服务器CPU占用较高等),在此总结一下: 1.代码中直接调用GC.Collect() 2.字符串等操作频繁的内存申请 3.频繁 ...
- ajax跨站请求伪造
用ajax提交数据到后台: {#<!DOCTYPE html>#} <html lang="en"> <head> <meta chars ...
- Dora.Interception,为.NET Core度身打造的AOP框架:全新的版本
Dora.Interception 1.0(Github地址:可以访问GitHub地址:https://github.com/jiangjinnan/Dora)推出有一段时间了,最近花了点时间将它升级 ...
- DFS入门__poj1979
Red and Black Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 26944 Accepted: 14637 D ...
- android仿微信红包动画、Kotlin综合应用、Xposed模块、炫酷下拉视觉、UC浏览器滑动动画等源码
Android精选源码 仿微信打开红包旋转动画 使用Kotlin编写的Android应用,内容你想象不到 Android手机上的免Root Android系统日志Viewer 一个能让微信 Mater ...
- Arduino 开源库 u8glib2 之 图标显示【原创】
Arduino 开源库 u8glib2 研究之 图标显示 -----------------关于drawXBM drawXBMP函数使用的研究 因为心血来潮,近来想做一个 ...
- rexray在CentOS上不能创建ceph rbd的docker volume问题定位
背景 我们通过docker的rexray插件来创建ceph rbd设备的docker volume,但总提示创建失败. # docker volume create --driver=rexray - ...