在C++中使用接口(抽象基类)时是否存在运行时性能损失?
简答:没有.
长答案:一个类在其层次结构中具有影响其速度的基类或祖先数量.唯一的问题是方法调用的成本.
非虚方法调用具有成本(但可以内联)
虚拟方法调用的成本略高,因为您需要在调用之前查找要调用的方法(但这是一个简单的表查找而不是搜索) .由于接口上的所有方法都是虚拟的,因此存在此成本.
除非您正在编写一些超高速敏感的应用程序,否则这应该不是问题.使用界面可以获得的额外清晰度通常可以弥补任何感知到的速度降低.
对虚函数有一种惩罚很容易忘记:在对象的类型不知道编译时的(常见)情况下,虚拟调用没有内联.如果你的函数很小并且适合内联,那么这个代价可能非常大,因为你不仅增加了调用开销,而且编译器也限制了它如何优化调用函数(它必须假设虚函数可能已经更改了一些寄存器或内存位置,它不能在调用者和被调用者之间传播常量值).
至于与正常函数调用相比的调用开销惩罚,答案取决于您的目标平台.如果您的目标是使用x86/x64 CPU的PC,则调用虚拟功能的代价非常小,因为现代x86/x64 CPU可以对间接调用执行分支预测.但是,如果您的目标是PowerPC或其他一些RISC平台,则虚拟呼叫损失可能非常大,因为在某些平台上从不预测间接呼叫(参见PC/Xbox 360跨平台开发最佳实践).
与常规呼叫相比,每个虚拟功能呼叫有一个小的惩罚.除非您每秒进行数十万次呼叫,否则您不太可能发现差异,并且价格通常值得支付以增加代码清晰度.
当您调用虚函数(例如通过接口)时,程序必须在表中查找函数以查看要为该对象调用的函数.与直接调用函数相比,这会带来一点点损失.
此外,当您使用虚函数时,编译器无法内联函数调用.因此,对于某些小功能使用虚函数可能会受到惩罚.这通常是您可能会看到的最大"性能".如果函数很小并且多次调用(例如在循环内),这实际上只是一个问题.