转载: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#中的虚函数及继承关系的更多相关文章

  1. 谈谈c++中继承中的虚函数

      c++继承中的虚函数 c++是一种面向对象的编程语言的一个很明显的体现就是对继承机制的支持,c++中继承分很多种,按不同的分类有不同分类方法,比如可以按照基类的个数分为多继承和单继承,可以按照访问 ...

  2. C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现

    tfref 前言 C++对象的内存布局 只有数据成员的对象 没有虚函数的对象 拥有仅一个虚函数的对象 拥有多个虚函数的对象 单继承且本身不存在虚函数的继承类的内存布局 本身不存在虚函数(不严谨)但存在 ...

  3. 关于在C#中构造函数中调用虚函数的问题

    在C#中如果存在类的继承关系,应避免在构造函数中调用虚函数.这是由于C#的运行机制造成的,原因如下: 新建一个类实例时,C#会先初始化该类(对类变量赋值,并将函数记在函数表中),然后再初始化父类.构造 ...

  4. 【整理】C++虚函数及其继承、虚继承类大小

    参考文章: http://blog.chinaunix.net/uid-25132162-id-1564955.html http://blog.csdn.net/haoel/article/deta ...

  5. C++中的虚函数解析[The explanation for virtual function of CPlusPlus]

    1.什么是虚函数?                                                                                            ...

  6. 【C++】C++中的虚函数与纯虚函数

    C++中的虚函数 先来看一下实际的场景,就很容易明白为什么要引入虚函数的概念.假设我们有一个基类Base,Base中有一个方法eat:有一个派生类Derived从基类继承来,并且覆盖(Override ...

  7. cc38b_demo_C++_异常_(2)txwtech在异常中使用虚函数-多态

    //cc38b_demo,21days_C++_异常_(2)txwtech20200121在异常中使用虚函数-多态 //--异常层次结构//*异常的类-创建自己的异常类//*异常派生-就是继承//*异 ...

  8. C++中的虚函数总结

    一.什么是虚函数.纯虚函数.抽象基类 虚函数:在某基类中声明为 virtual 并在一个或多个派生类中被重新定 义的成员函数. 纯虚函数:是一种特殊的虚函数,使用virtual关键字,并且在其后面加上 ...

  9. C++箴言:避免构造或析构函数中调用虚函数

    如果你已经从另外一种语言如C#或者Java转向了C++,你会觉得,避免在类的构造函数或者析构函数中调用虚函数这一原则有点违背直觉.但是在C++中,违反这个原则会给你带来难以预料的后果和无尽的烦恼. 正 ...

随机推荐

  1. IEnumerable<T>和IQueryable<T>区分

    LINQ查询方法一共提供了两种扩展方法,在System.Linq命名空间下,有两个静态类:Enumerable类,它针对继承了IEnumerable<T>接口的集合进行扩展:Queryab ...

  2. MySQL 笔记整理(9) --普通索引和唯一索引,应该怎么选择?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 9) --普通索引和唯一索引,应该怎么选择? 假如你在维护一个市民系统, ...

  3. 基于 Docker 的微服务架构实践

    本文来自作者 未闻 在 GitChat 分享的{基于 Docker 的微服务架构实践} 前言 基于 Docker 的容器技术是在2015年的时候开始接触的,两年多的时间,作为一名 Docker 的 D ...

  4. Spring Boot 整合 elasticsearch

    一.简介 我们的应用经常需要添加检索功能,开源的 ElasticSearch 是目前全文搜索引擎的 首选.他可以快速的存储.搜索和分析海量数据.Spring Boot通过整合Spring Data E ...

  5. javaweb中上传图片并显示图片,用我要上传课程信息(里面包括照片)这个例子说明

    原理:  从客户端上传到服务器                照片——文件夹——数据库 例如:桌面一张照片,在tomacat里创建upload文件夹,把桌面照片上传到upload文件夹里,并且把照片的 ...

  6. 【大数据】了解Hadoop框架的基础知识

    介绍 此Refcard提供了Apache Hadoop,这是最流行的软件框架,可使用简单的高级编程模型实现大型数据集的分布式存储和处理.我们将介绍Hadoop最重要的概念,描述其架构,指导您如何开始使 ...

  7. Vue UI:Vue开发者必不可少的工具

    译者按: Vue开发工具越来越好用了! 原文: Vue UI: A First Look 译者: Fundebug 本文采用意译,版权归原作者所有 随着最新的稳定版本Vue CLI 3即将发布,是时候 ...

  8. 20190322-a标签、img标签、三列表、特殊字符实体、表格

    目录 1.a标签 a标签的属性 锚点 2.img标签 img标签的属性 图像热区 3.三列表 有序列表(Ordered List)     ol>li 无序列表(Unordered List)  ...

  9. windows相关命令记录

    1.regedit 打开注册表 2.services.msc 打开服务列表 3.net start/stop 服务名 打开/关闭服务,例:net start mysql57,可以通过服务列表开启/关闭 ...

  10. 如何解决angular不自动生成spec.ts文件

    "schematics":{   "@schematics/angular:component": {        "styleext": ...