在c+;中禁用动态绑定(虚拟表创建)+;虚拟函数 最近我遇到了一个C++面试问题,这使我很感兴趣: 假设您错误地将某些C++成员函数声明为虚函数,但(可能出于性能原因),您希望阻止编译器为该函数创建V表。也就是说,禁用动态函数绑定而使用静态绑定

在c+;中禁用动态绑定(虚拟表创建)+;虚拟函数 最近我遇到了一个C++面试问题,这使我很感兴趣: 假设您错误地将某些C++成员函数声明为虚函数,但(可能出于性能原因),您希望阻止编译器为该函数创建V表。也就是说,禁用动态函数绑定而使用静态绑定,c++,performance,c++11,vtable,C++,Performance,C++11,Vtable,你将如何做到这一点?另外,是否有一些C++11特定的方法可以做到这一点?您可以通过禁用RTTI来避免开销……有一个编译时开关可以实现这一点 P>动态表的投递/ Type ID不会有任何开销,一旦启用RTTI禁用标志。 < P>我知道没有强制强制C++编译器禁用动态绑定的方法,只要它支持C代码,如果它支持这样的选项(它不是所有C++编译器都做的,但大多数都是这样)的话。然而,这是一种用洗澡水把婴儿扔掉的方法,因为它实际上禁用了所有不是C./P>部分的C++特征。 当然,C++11中引入了fina

你将如何做到这一点?另外,是否有一些C++11特定的方法可以做到这一点?

您可以通过禁用RTTI来避免开销……有一个编译时开关可以实现这一点


<> P>动态表的投递/ Type ID不会有任何开销,一旦启用RTTI禁用标志。

< P>我知道没有强制强制C++编译器禁用动态绑定的方法,只要它支持C代码,如果它支持这样的选项(它不是所有C++编译器都做的,但大多数都是这样)的话。然而,这是一种用洗澡水把婴儿扔掉的方法,因为它实际上禁用了所有不是C./P>部分的C++特征。 当然,C++11中引入了
final
标识符,它阻止了进一步从类派生或重写虚拟成员。严格地说,这并不能阻止动态调度——它解决了一个不同的问题

避免动态绑定影响(感知的或实际的)的一种方法是避免使用或编写具有虚拟成员函数的任何类,并且不要创建类层次结构(即,不要从具有虚拟函数的类派生)。显然,如果没有虚拟函数在起作用,就不需要虚拟函数分派,因此也不需要动态绑定

如果您知道对象的类型,则可以通过使用静态分派(即显式命名要调用的函数)来避免使用动态绑定。例如,假设我们有一个名为
foo()
的类
Base
,它提供了一个名为
public
virtual
成员,以及一个名为
Derived
的类,该类继承自
Base
并重写
foo()
。然后避免执行动态调度

 Base *b = new Derived;
 b->Base::foo();          //   static call;  will not call `Derived::foo()`
 b->Derived::Foo();       // incorrect static call.  Will not compile since b is a pointer to Base not Derived

 Derived *d = new Derived;
 d->Derived::foo();       // static call of Derived::foo()
 d->Base::foo();          // static call of Base::foo()
当然,如果使用对象的代码依赖于对对象的实际类型的了解,或者依赖于调用的
foo()
的特定变体,那么它的设计某种程度上违背了拥有多态基类和从中派生的其他类的目的

在上面的例子中,编译器仍然支持虚拟函数调用(vtable等,如果编译器现在可以工作的话),这可能会影响创建和销毁对象的过程

另一种避免动态分派(或绑定)的技术是使用模板(有时称为编译时多态性)。从本质上讲,模板可以假定一个类型提供了一些接口(或一组操作),并将使用该接口处理任何类型的变量。比如,

 struct X
 {
      void foo();
 };

 template<class T> void func()
 {
      T x;          // relies on T being instantiable (and destructible)
      x.foo();      // relies on T having a member named foo()
 }

 // in some function somewhere where both X and func() are known to the compiler

 func<X>();
struct X
{
void foo();
};
模板void func()
{
tx;//依赖于T是可实例化的(和可破坏的)
x、 foo();//依赖于T有一个名为foo()的成员
}
//在编译器已知X和func()的某个函数中
func();
这样的模板不需要类型
T
来具有虚拟函数,因此不依赖于动态分派(绑定)。但是,没有任何东西可以阻止这样的模板函数与具有虚拟成员函数的类一起工作,因此这不会禁用动态绑定-它只允许程序员做出选择以避免使用动态绑定


如果我在采访中被问到这个问题,我可能会指出上面所有的问题,但不要说这个问题相当愚蠢。一个了解C++的面试官会意识到这一点,并且对你如何思考和解决这样的问题感兴趣。(管理层或客户经常要求所有现实世界的开发人员满足愚蠢或不切实际的要求,并希望他们足够机智,避免告诉他们的经理或客户他们是愚蠢的。)如果面试官在不理解的情况下问问题(或者在没有其他面试小组成员的情况下,我也不想和那个雇主一起工作。

重写代码库中依赖于动态绑定的所有内容…:D(说真的,在面试中,我总是对愚蠢的问题给出愚蠢的答案,这很有效)如果使用虚拟函数,则有一个虚拟表。如果不需要虚拟表,则不要使用虚拟表functions@Gombat如果你有一个VTABLE仅仅是编译器实现特定的,C++标准就不会陈述这样的概念。@ StGATLYV:但是如果你只删除虚拟关键词,你的程序就会错误地工作。不坏,或者你在解释问题时改变了意思。不管怎样,可能他们只是问如何绕过虚拟绑定,直接调用特定类的绑定,如
name::function(…)
但是在禁用rtti之前,您必须注意动态强制转换/类型id的使用。我想这就是面试官的意思。没有rtti并不意味着没有vtables。同意。但是“禁用动态绑定功能”在问题中,我想,也许这就是面试官的意思。谢谢大家的评论。如果有任何编译时标志关闭RTTI,请让我知道。这可能是我问题的可能答案。这应该对你有帮助。说得好。谢谢彼得。