从派生指针调用虚函数而不支付vtable价格

时间:2017-09-29 09:07:08

标签: c++ performance polymorphism vtable

考虑这个简单的例子:

class Base {
    virtual void foo() {};  
};

class Derived: public Base {
    void foo() {}; 
}; 

Base    *b = new Derived;
Derived *d = new Derived;
b->foo();
d->foo();

我的问题是:通过派生类指针调用在基类(但不在派生类中)中声明为虚拟的成员函数是否使用vtable机制(并付出代价)?在示例b->foo()中使用vtable机制来调用Derived::foo(),但是d->foo()

如果是,那么如何规避这种行为:当明确使用Derived指针时,我想直接调用Derived::foo()方法而不支付vtable的成本,就好像基类没有存在?

2 个答案:

答案 0 :(得分:6)

语法

d->Derived::foo();

将禁止虚拟调度,并保证函数Derived::foo是被调用的函数,即使存在重写函数也是如此。

这很少是你想要的,但我不能建议其他解决方案,除非你解释为什么要这样做。例如,在给出的代码片段中,没有理由为什么应该动态分配Derived。你可以写一下:

Derived d;
d.foo();

这里,编译器确定动态类型为Derived,因此不需要虚拟调度。

答案 1 :(得分:2)

  

调用在基类中声明为virtual的成员函数(但不在deverived类中)...

我已停止阅读此处,因为如果Basefoo声明为虚拟,Derived只能覆盖fooDerived::foo(据称是签名匹配) )隐含virtual

Derived::foo的以下定义相同

class Derived: public Base {
  void foo() {}; 
};

class Derived: public Base {
  virtual void foo() {}; 
};

此机制称为隐式虚拟传播,this SO answer tries and explain why id was conceived that way。以下是它的基本原理:

  

10.3虚拟功能

     

2如果在类vf和类Base中声明虚拟成员函数Derived,直接或间接从Base派生,则成员函数{{ 1}}具有相同的名称,声明参数类型列表(8.3.5),cv-qualification和ref-qualifier(或缺少相同)vf,然后Base::vf也是虚拟(是否如此声明)并覆盖Derived::vf