首页 > 其他分享 >虚方法

虚方法

时间:2024-04-27 14:34:59浏览次数:14  
标签:Console Sum am class 实例 方法 void

若一个实例方法声明前带有virtual关键字,那么这个方法就是虚方法。
虚方法与非虚方法的最大不同是,虚方法的实现可以由派生类所取代,这种取代是通过方法的重写实现的(以后再讲)
虚方法的特点:
虚方法前不允许有static,abstract,或override修饰符
虚方法不能是私有的,因此不能使用private修饰符
虚方法的执行:
我们知道一般函数在编译时就静态地编译到了执行文件中,其相对地址在程序运行期间是不发生变化的,
而虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它会根据运行时期对象实例来动态判断要调用的函数,
其中那个申明时定义的类叫申明类,那个执行时实例化的类叫实例类。
如:A a =new B(); 其中A是申明类,B是实例类。
1.当调用一个对象的函数时,系统会直接去检查这个对象申明定义的类,即申明类,看所调用的函数是否为虚函数;
2.如果不是虚函数,那么它就直接执行该函数。而如果是一个虚函数,那么这个时候它就不会立刻执行该函数了,而是开始检查对象的实例类。
3.在这个实例类里,他会检查这个实例类的定义中是否有实现该虚函数或者重新实现该虚函数(通过override关键字)的方法,
如果有,它就不会再找了,而是马上执行该实例类中实现的虚函数的方法。而如果没有的话,系统就会不停地往上找实例类的父类,
并对父类重复刚才在实例类里的检查,直到找到第一个重载了该虚函数的父类为止,然后执行该父类里重载后的函数。
例1:

复制代码 复制代码
    class A
{
public virtual void Sum()
{
Console.WriteLine("I am A Class,I am virtual sum().");
}
}
class Program
{
static void 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
{
public virtual void Sum()
{
Console.WriteLine("I am A Class,I am virtual sum().");
}
}
class B : A
{
public override void Sum() // 重新实现了虚函数
{
Console.WriteLine("I am B Class,I am override sum().");
}

}
class Program
{
static void 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
{
public virtual void Sum()
{
Console.WriteLine("I am A Class,I am virtual sum().");
}
}
class B : A
{
public override void Sum() // 重新实现了虚函数
{
Console.WriteLine("I am B Class,I am override sum().");
}

}
class C : B
{

}
class Program
{
static void 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
{
public virtual void Sum()
{
Console.WriteLine("I am A Class,I am virtual sum().");
}
}
class B : A
{
public new void Sum() //覆盖父类里的同名函数,而不是重新实现
{
Console.WriteLine("I am B Class,I am new sum().");
}

}
class Program
{
static void 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
{
public virtual void Sum()
{
Console.WriteLine("I am A Class,I am virtual sum().");
}
}
class B : A
{
public new void Sum() //覆盖父类里的同名函数,而不是重新实现
{
Console.WriteLine("I am B Class,I am new sum().");
}

}
class Program
{
static void Main(string[] args)
{
B b=new B();
b.Sum();
Console.Read();
}
}
复制代码 复制代码

执行B类里的Sum(),输出结果I am B Class,I am new sum(). 
可以使用抽象函数重写基类中的虚函数吗?
答案是可以的。

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

密封类可以有虚函数吗?
可以,基类中的虚函数将隐式的转化为非虚函数,但密封类本身不能再增加新的虚函数

复制代码 复制代码
    class A
{
public virtual void Fun()
{
Console.WriteLine("I am A.");
}
}
sealed class Program:A
{
public override void Fun()
{
Console.WriteLine("I am B.");
}
static void Main(string[] args)
{
Program p = new Program();
p.Fun();
Console.Read();
}
}
复制代码

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,并在文章页面明显位置以超链接形式注明出处,否则保留追究法律责任的权利。

转自:http://www.cnblogs.com/jiajiayuan/archive/2011/09/14/2176015.html

复制代码

标签:Console,Sum,am,class,实例,方法,void
From: https://www.cnblogs.com/caiwenwen/p/18162012

相关文章

  • MyBatis-Plus QueryWrapper常用方法
    1queryWrapper.lt();//小于2queryWrapper.le();//小于等于3queryWrapper.gt();//大于4queryWrapper.ge();//大于等于5queryWrapper.eq();......
  • vue,js直接导出excel,xlsx的方法,XLSX_STYLE 行高设置失效的问题解决
    1、先安装依赖:xlsx、xlsx-style、file-saver三个包npminstallxlsxxlsx-stylefile-saver2、引入:<script>import*asXLSXfrom'xlsx/xlsx.mjs'importXLSX_STYLEfrom'xlsx-style';import{saveAs}from'file-saver';exportdefau......
  • 为什么动态代理只能覆盖 public 方法
    动态代理只能覆盖public方法的原因主要是因为Java的访问权限控制。在Java中,动态代理是通过生成一个继承自Proxy类并实现了指定接口的代理类来实现的。这个代理类必须能够访问被代理对象的方法,但是如果被代理对象的方法不是public,则代理类无法访问这些方法,因此也就无法覆......
  • dotnet C# 简单的追加文件夹到 ZipArchive 压缩文件的方法
    本文将告诉大家一个在ZipArchive里追加文件夹,以及添加过滤文件处理的压缩文件辅助方法实现的方法的代码如下///<summary>///追加文件夹到压缩文件里面///</summary>///<paramname="archive"></param>///<paramname="sourceDirectoryName"></p......
  • 改善员工绩效管理的 8 种最佳方法
    企业如何改进绩效管理体系,才能获得最好的结果?请仔细阅读,找出答案…人力资源部门对组织的成功起着至关重要的作用,组织的员工也是如此。更好的组织管理会带来更高的利润。人力资源部门的工作很大一部分就是规范绩效管理体系,营造员工能做出最好的工作、发挥最大能力的工作氛围。在......
  • Mac 卸载 PyCharm 方法
    Mac系统下PyCharm没有一键卸载程序,也没有完全卸载的插件,若要彻底删除,除了在应用(Application)里删除PyCharm到垃圾桶外,还需要在终端(Terminal)执行删除相应的文件及文件夹。1卸载列表 1.1删除应用程序文件 1.2删除应用支持文件 1.3删除偏好设置数据 1.4删除缓存数据 1.5删除日志......
  • 为 AntdUI 扩展一个 MessageBox 方法
    AntdUI是个很不错的开源WinFrom界面组件,使用中感觉消息对话框调用有点麻烦,于是按照MessageBox.Show的使用习惯,增加了一个扩展方法来调用,废话不多说,直接上代码。1usingSystem.Windows.Forms;23namespaceAntdUI4{5publicstaticclassWindowExtent......
  • sql语句优化的30种方法
    作者:羋虹光链接:https://www.jianshu.com/p/3ab117c83d0b1.对查询进行优化,应尽量避免全表扫描,首先应考虑在where及orderby涉及的列上建立索引。2.应尽量避免在where子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。3.应尽量避免在where子句中对字段进......
  • 功率分析仪中关于IEC标准中Flicker的使用方法及相关参数意义
     电力系统中的闪变(Flicker)是由于电压波动或电流波动引起的视觉不稳定现象,它主要影响灯光的亮度变化,导致不适感或视觉干扰。在工业应用中,特别是对于连接到电网的设备,重要的是要监测并控制闪变,以确保符合国际电工委员会(IEC)的标准。IEC标准中关于闪变的最关键部分是IEC 61000-4-......
  • ROS2学习--OOP方法编写python节点
    1.创建工作空间mkdir-ptown_ws/srccdtown_ws/src2.创建功能包ros2pkgcreatevillage_li--build-typeament_python--dependenciesrclpypkgcreate是创建包的意思--build-type用来指定该包的编译类型,一共有三个可选项ament_python、ament_cmake、cmake--dependen......