在C++中,我的理解是虚函数可以内联,但通常会忽略对内联的提示。看起来内联虚函数并没有太多意义。
是那么回事吗?
谁能给出一个内联虚函数好用的例子?
发布于 2010-01-25 12:47:25
在正常情况下,虚函数将通过指向函数(包含在类的vtable中)的指针来调用。在这种情况下,只有当编译器可以静态地确定函数将被调用的实际类型,而不仅仅是它必须是类X或从X派生的东西时,才能内联生成虚函数调用。
内联虚函数有意义的主要时候是当你有一个性能关键的情况,并且知道一个类将经常以一种允许编译器静态地确定实际类型的方式使用(并且至少有一个目标编译器通过指针优化了调用)。
发布于 2010-01-25 14:05:05
为了完整地回答这个问题,需要理解virtual
的属性独立地应用于函数本身和对该函数的调用。有虚拟函数和非虚拟函数。有对这些函数的虚拟调用和非虚拟调用。
作为inline
的属性也是如此。有内联函数和非内联函数。并且存在对这些函数的内联和非内联调用。
这些属性- virtual
和inline
-在应用于函数本身时不会冲突。他们根本没有理由也没有机会发生冲突。inline
说明符为函数本身所做的唯一更改是,它修改了该函数的一个定义规则:该函数可以在多个翻译单元中定义(并且必须在使用它的每个翻译单元中定义)。virtual
说明符唯一的变化是包含该函数的类变得多态。它对函数本身没有实际影响。
因此,同时声明函数virtual
和inline
绝对没有问题。没有任何冲突的基础。这在C++语言中是完全合法的。
struct S {
virtual void foo();
};
inline void S::foo() // virtual inline function - OK, whatever
{
}
然而,当人们问这个问题时,他们通常对函数本身的属性不感兴趣,而是对函数调用的特征感兴趣。
虚拟调用的定义特性是它在运行时被解析,这意味着通常不可能内联真正的虚拟调用:
S *s = new SomeType;
s->foo(); // virtual call, in general case cannot be inlined
但是,如果调用本身是非虚拟的(即使它转到虚拟函数),内联根本不是问题:
S *s = new SomeType;
s->S::foo(); // non-virtual call to a virtual function, can easily be inlined
当然,在某些情况下,优化编译器可能能够在编译时找出虚拟调用的目标,甚至内联这样的虚拟调用。在某些情况下,这很简单:
S ss;
ss.foo(); // formally a virtual call, but in practice it can easily be inlined
在某些情况下,它更复杂,但仍然可行:
S *s = new S;
s->foo(); // virtual call, but a clever compiler might be able
// to figure out that it can be inlined
发布于 2010-01-25 13:22:08
您可以将虚函数作为内联函数。使函数调用内联的决定不仅仅是在编译时做出的。它可以是从编译到rutime的任何时间。你可以参考Herb Sutter的这篇文章。Inline Redux
https://stackoverflow.com/questions/2130226
复制相似问题