当实例方法声明包含 virtual 修饰符时,称该方法为虚拟方法。不存在 virtual 修饰符时,称该方法为非虚拟方法。
非虚拟方法的实现是不变的:无论是在声明它的类的实例上调用该方法还是在派生类的实例上调用,实现都是相同的。与此相反,虚拟方法的实现可以由派生类取代。取代所继承的虚拟方法之实现的过程称为重写方法
在虚拟方法调用中,为其进行调用的实例的运行时类型确定要调用的实际方法实现。在非虚拟方法调用中,实例的编译时类型是决定性因素。准确地说,当在具有编译时类型 C 和运行时类型 R 的实例(其中 R 为 C 或者从 C 派生的类)上用参数列表 A 调用名为 N 的方法时,调用按下面这样处理:
首先,将重载决策应用于 C、N 和 A,以从在 C 中声明和由 C 继承的方法集中选择一个特定方法 M。
然后,如果 M 为非虚拟方法,则调用 M。
否则,M 为虚拟方法,调用就 R 而言 M 的派生程度最大的实现。
对于在类中声明或者由类继承的每个虚拟方法,存在一个就该类而言的派生程度最大的实现。就类 R 而言虚拟方法 M 的派生度最大的实现按下面这样确定:
如果 R 包含 M 的引入 virtual 声明,则这是 M 的派生程度最大的实现。
否则,如果 R 包含 M 的 override,则这是 M 的派生程度最大的实现。
否则,M 的派生程度最大的实现与 R 的直接基类的派生程度最大的实现相同。 |