C#的虚函数解析机制

前言

这篇文章出自我个人对C#虚函数特性的研究和理解,未参考、查阅第三方资料,因此很可能存在谬误之处。我在这里只是为了将我的理解呈现给大家,也希望大家在看到我犯了错误后告诉我。

用词约定

“方法的签名”包括返回类型、方法名、参数列表,这三者共同标识了一个方法。

“声明方法”,即指出该方法的签名。“定义方法”,则是指定调用方法时执行的代码。

“同名方法”是指方法的签名相同的两个方法。

“重写”一个方法,意味着子类想继承父类对方法的声明,却想重新定义该方法。

单独使用“使用”一词时,包括“显式”或“隐式”两种使用方式:前者是指在代码中指明,后者是根据语句的上下文推断。

某个类的方法,包括了在该类中定义的方法,以及由继承得到的直接父类的方法。注意这条规则的递归性质。 

理论部分

在父类与子类里,除了类之间的继承链,还存在方法之间的继承链。

C#里,在一个类中声明一个方法时,有四个和方法的继承性有关的关键字:new、virtual、sealed、override。

virtual 表示允许子类的同名方法与其①建立继承链。

override 表示其①与父类的同名方法之间建立了继承链,并隐式使用 virtual 关键字。

new 表示其切断了其①与父类的同名方法之间的继承链。

sealed 表示将其①与父类的同名方法建立继承链(注意这个就是 override 关键字的特性),并且不允许子类的同名方法与其建立继承链。在使用 sealed 关键字时,必须同时显式使用 override 关键字。

以及:

在定义方法时,若不使用以上关键字,方法就会具有new关键字的特性。对于这一点,如果父类中没有同名方法,则没有任何影响;如果父类中存在一个同名方法,编译器会给出一个警告,询问你是否是想隐藏父类的同名方法,并推荐你显式地为其指定new关键字。

①其:指代正在进行声明的方法。

依照上述的说明,在调用类上的某个方法时,可以为该方法构建出一个或多个“方法继承链”。首先列出从子类②一直到父类③的类继承链,并列出这些类对该方法的最初定义或重定义。然后从父类到子类,逐个检查每个类对该方法的定义,按以下规则构造方法继承链:

任何一个没有使用 override 或 sealed 关键字的方法定义都将成为继承链的开端;

如果该类在定义方法时使用了 virtual 关键字,则会被附加到继承链中。

继承链的结束取决于两个因素:若子类中存在使用了 new 关键字的同名方法,则之前的继承链立刻结束(该方法不会被添加到继承链中);若子类中存在使用了 sealed 关键字的同名方法,则在将该方法添加到继承链后,然后结束继承链。

当你拿到一个子类②的实例,却使用父类③的对象引用调用一个方法时(例如“A instanceRef = new C(); instanceRef.Foo1()”,这时类型A的引用就指向了类型C的对象),C#会先检查该方法是否为一个虚方法(使用了 virtual 关键字):如果不是,则简单地调用该方法的父类③版本即可;如果是,则沿着方法的继承链向下寻找,找到位于继承链底部的那个方法。

②子类:指该实例的实际类型。

③父类:指在调用方法时,使用的对象引用的类型;该类型必然是子类的父类型。

时间: 2024-10-31 13:00:03

C#的虚函数解析机制的相关文章

C++虚函数解析(转)

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/hairetz/archive/2009/04/29/4137000.aspx  C++ 中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技 术可以让父类的指针有"多种形态",这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚 函数技术,要么是试图做到在编

C++虚函数的实现机制分析_C 语言

本文针对C++的虚函数的实现机制进行较为深入的分析,具体如下: 1.简单地说,虚函数是通过虚函数表实现的.那么,什么是虚函数表呢? 事实上,如果一个类中含有虚函数,则系统会为这个类分配一个指针成员指向一张虚函数表(vtbl),表中每一项指向一个虚函数的地址,实现上就是一个函数指针的数组. 例如下面这个例子: class Parent { public: virtual void foo1() { } virtual void foo1() { } void foo1(); }; class Ch

C++中虚函数与纯虚函数的用法_C 语言

本文较为深入的分析了C++中虚函数与纯虚函数的用法,对于学习和掌握面向对象程序设计来说是至关重要的.具体内容如下: 首先,面向对象程序设计(object-oriented programming)的核心思想是数据抽象.继承.动态绑定.通过数据抽象,可以使类的接口与实现分离,使用继承,可以更容易地定义与其他类相似但不完全相同的新类,使用动态绑定,可以在一定程度上忽略相似类的区别,而以统一的方式使用它们的对象. 虚函数的作用是实现多态性(Polymorphism),多态性是将接口与实现进行分离,采用

[面试珠玑]一道关于C++虚函数和多继承的面试题

问题:假设有两个基类A和B,它们有一个相同签名的虚函数void foo(), 但是拥有不同的实现.现在要求创建一个新类C,它同时继承A和B,也有相同的签名的函数void foo(), 并能分别对A和B中的foo函数进行重写(overwrite).     已知条件对应的代码如下: class A{ public: virtual void foo(){ cout<<"A::foo()"<<endl; } }; class B{ public: virtual v

C++中虚函数功能的实现机制

  要理解C++中虚函数是如何工作的,需要回答四个问题. 1. 什么是虚函数. 虚函数由于必须是在类中声明的函数,因此又称为虚方法.所有以virtual修饰符开始的成员函数都成为虚方法.此时注意是virtual修饰的成员函数不是virtual修饰的成员函数名. 例如:基类中定义: virtual void show(); //由于有virtual修饰因此是虚函数 voidshow(int); //虽然和前面声明的show虚函数同名,但不是虚函数. 所有的虚函数地址都会放在所属类的虚函数表vtbl

深入解析C++编程中的纯虚函数和抽象类_C 语言

C++纯虚函数详解 有时在基类中将某一成员函数定为虚函数,并不是基类本身的要求,而是考虑到派生类的需要,在基类中预留了一个函数名,具体功能留给派生类根据需要去定义. 纯虚函数是在声明虚函数时被"初始化"为0的函数.声明纯虚函数的一般形式是 virtual 函数类型 函数名 (参数表列) = 0; 关于纯虚函数需要注意的几点: 纯虚函数没有函数体: 最后面的"=0"并不表示函数返回值为0,它只起形式上的作用,告诉编译系统"这是纯虚函数"; 这是一个

深入解析C++中的虚函数与多态_C 语言

1.C++中的虚函数C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有"多种形态",这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Tab

C++虚函数及虚函数表解析

一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数.纯虚函数(Pure Virtual Function):基类中没有实现体的虚函数称为纯虚函数(有纯虚函数的基类称为虚基类).C++  "虚函数"的存在是为了实现面向对象中的"多态",即父类类别的指针(或者引用)指向其子类的实例,然后通过父类的指针(或者引用)调用实际子类的成员函数.通过动态赋值,实现调用不同的子类的成员

虚函数

一. 什么是虚函数 1. 虚函数是面向对象编程中函数的一种特定形态,是C++中用于实现多态的一种有效机制 2. 虚函数用virtual修饰函数名,虚函数的作用是在程序的运行阶段动态的选择合适的成员函数,在定义了虚函数之后,可以在基类的派生类中对虚函数进行重定义,在派生类中重定义的函数与基类虚函数具有相同的函数返回值.函数参数列表.函数名等.如果派生类中没有重定义基类的虚函数则它是直接继承基类的虚函数 3. 定义虚函数的一般格式 class <类名>{ public:         virtu