虚拟功能具有明确的内在价值; 使用它们可以使体系结构更加灵活,并解决大量设计问题。
关于虚拟功能 (或方法,在这种情况下,术语的区别并不奏效)有两种主要的表现思想流派。 首先是他们很慢,过去一直,而且永远都会。 这所学校的人们会告诉您,他们在游戏中使用太慢。 其次,它们曾经很慢,但是现代的编译器和体系结构使它们高效。 这所学校的人们会告诉您自由使用它们,甚至在性能关键的代码中也是如此,因为它们基本上是免费的。
那么,真相是什么? 毫不奇怪的答案是:取决于情况。 依靠什么? 好吧,很高兴你问。 答案像大多数间接寻址一样,主要取决于缓存以及应用程序与之交互的方式。 在本文中,我将深入探讨三件事(着重于C ++):
- 如何避免虚拟功能的性能下降。 我将展示如何直接调用虚函数并避免间接开销。
- 如何快速批量处理虚拟函数 。 这是游戏引擎中的一个常见问题,其中一个场景可能具有成千上万个对象,每个对象都具有多个未必唯一的更新功能。 如果这些更新以帧速率发生,那么每秒将有数以万计的呼叫。
- 如何检测虚拟功能是否已被覆盖。 这是现代游戏引擎中的另一个常见问题,在游戏引擎中有很多功能需要覆盖。 例如,Unity有64个这样的可重写方法(它们称它们为message ),对于大多数对象而言,大多数是无操作的。 当检测到此问题时,引擎可以完全避免调用它们。
我不会谈论为什么虚函数有用。
了解虚函数和VTable
在探讨虚拟功能的性能之前,我想花一点时间来研究虚拟功能的工作原理。 如果您是虚拟函数专家,请随时跳过本节。
让我们从创建没有虚函数的类层次结构开始。 我们将创建仅用名字给别人打招呼的人:

现在,我们可以更新场景管理器,以仅在新对象覆盖了适当的功能时有条件地向每个批次添加新对象:
就这么简单! 当然,您可能想开始将它们包装在更好的类中。 您还可以使用一些宏魔术来确保您的VTable结构始终与该类中实际定义的匹配。
结论
希望您已经看到了使用VTable可以有多大用处-而且还不那么难。 我鼓励您自己尝试一下。 最终结果将是更快的程序和更快乐的开发人员。 能够像这样编写代码让人非常满意:
不必担心不必要的开销或注册功能。
所有示例和测试的完整源代码都在GitHub上。 骇客骇客!