C#中的虚函数及继承关系
转载:http://blog.csdn.net/suncherrydream/article/details/8423991
若一个实例方法声明前带有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();
}
}
C#中的虚函数及继承关系的更多相关文章
- 谈谈c++中继承中的虚函数
c++继承中的虚函数 c++是一种面向对象的编程语言的一个很明显的体现就是对继承机制的支持,c++中继承分很多种,按不同的分类有不同分类方法,比如可以按照基类的个数分为多继承和单继承,可以按照访问 ...
- C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现
tfref 前言 C++对象的内存布局 只有数据成员的对象 没有虚函数的对象 拥有仅一个虚函数的对象 拥有多个虚函数的对象 单继承且本身不存在虚函数的继承类的内存布局 本身不存在虚函数(不严谨)但存在 ...
- 关于在C#中构造函数中调用虚函数的问题
在C#中如果存在类的继承关系,应避免在构造函数中调用虚函数.这是由于C#的运行机制造成的,原因如下: 新建一个类实例时,C#会先初始化该类(对类变量赋值,并将函数记在函数表中),然后再初始化父类.构造 ...
- 【整理】C++虚函数及其继承、虚继承类大小
参考文章: http://blog.chinaunix.net/uid-25132162-id-1564955.html http://blog.csdn.net/haoel/article/deta ...
- C++中的虚函数解析[The explanation for virtual function of CPlusPlus]
1.什么是虚函数? ...
- 【C++】C++中的虚函数与纯虚函数
C++中的虚函数 先来看一下实际的场景,就很容易明白为什么要引入虚函数的概念.假设我们有一个基类Base,Base中有一个方法eat:有一个派生类Derived从基类继承来,并且覆盖(Override ...
- cc38b_demo_C++_异常_(2)txwtech在异常中使用虚函数-多态
//cc38b_demo,21days_C++_异常_(2)txwtech20200121在异常中使用虚函数-多态 //--异常层次结构//*异常的类-创建自己的异常类//*异常派生-就是继承//*异 ...
- C++中的虚函数总结
一.什么是虚函数.纯虚函数.抽象基类 虚函数:在某基类中声明为 virtual 并在一个或多个派生类中被重新定 义的成员函数. 纯虚函数:是一种特殊的虚函数,使用virtual关键字,并且在其后面加上 ...
- C++箴言:避免构造或析构函数中调用虚函数
如果你已经从另外一种语言如C#或者Java转向了C++,你会觉得,避免在类的构造函数或者析构函数中调用虚函数这一原则有点违背直觉.但是在C++中,违反这个原则会给你带来难以预料的后果和无尽的烦恼. 正 ...
随机推荐
- webpack4.0各个击破(2)—— CSS篇
webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...
- 树莓派3B+通过路由器进SSH和VNC
1.打开树莓派官网 www.raspberrypi.org 选择 ”Raspbian Stretch with desktop and recommended software“ 并下载 镜像包含推荐 ...
- windows下Jmeter压力测试工具的安装
JMeter是Apache软件基金会的产品,用于对静态的和动态的资源(文件,Servlet,Perl脚本,Java 对象,数据库和查询,FTP服务器等等)的性能进行测试.是一款很方便的测试软件. 系统 ...
- 页面内容不够高footer始终位于页面的最底部
相信很多前端工程师在开发页面时会遇到这个情况:当整个页面高度不足以占满显示屏一屏,页脚不是在页面最底部,用户视觉上会有点不好看,想让页脚始终在页面最底部,我们可能会想到用: 1.min-height来 ...
- jsp基础语言-jsp动作
jsp动作是一组jsp内置的标签,用来控制jsp的行为,执行一些常用的jsp页面动作.通过jsp动作实现使用多行java代码能够实现的效果,即对常用的jsp功能进行抽象与封装. jsp共有七种标准的“ ...
- 少侠学代码系列(一)->JS起源
少侠:喂,有人吗?赶紧出来接客了,有没有人啊 帅气的我:来了来了,少侠有何吩咐? 少侠:把你们店里的秘籍呈上来我要学JS 帅气的我:少侠,别这样,我们秘籍是不外传的,祖上传下来的规矩,传人妖不传男女. ...
- 自然底数e的意义是什么?
自然底数e的意义是什么? https://mp.weixin.qq.com/s?__biz=MzA5ODUxOTA5Mg==&mid=2652553811&idx=1&sn=0 ...
- 如何在WIN10内置Ubuntu中有多个terminal
使用的是tmux来实现在WIN10的内置Ubuntu实现多终端窗口 先安装tmux:sudo apt-get install tumx 启动tmux,tmux 然后就可以在tmux中实现多窗口.其操作 ...
- Visual Studio 无法记忆标签页、断点等的解决办法
1.到工程目录删除*.suo文件 2.*.suo默认是隐藏的,需要打开查看隐藏文件的开关
- java设计模式——适配器模式 Java源代码
前言:适配器模式就是把一个类的接口变换成客户端所能接受的另一种接口,从而使两个接口不匹配而无法在一起工作的两个类能够在一起工作.通常被用在一个项目需要引用一些开源框架来一起工作时,这些框架的内部都有一 ...