当我在派生类中添加额外的虚拟功能时,什么是开销

When I add an extra virtual function to a derived class, what is the overhead?

本文关键字:功能 虚拟 什么 开销 派生 添加      更新时间:2023-10-16

我正在通过Marshall Cline的C 常见问题 - 特别是有关在编译器中如何实现虚拟函数的链接。

似乎在说派生类的VPTR存在于对象的基类部分中。当创建了派生类的实例时,在派生类部分中并未创建另一个VPTR-简单的基类部分中已经存在的VPTR是初始化的,以指向正确的VTable。

我的问题是:如果我在派生类中声明虚拟函数,那不在基类中,什么是开销?是否在派生类部分中创建了额外的VPTR?还是以相同的方式完成,即基类部件中的VPTR被分配给特定的VTable?

so-要使我的问题更具体 - 在下面的示例中,编译器是否会给Apple类额外的VTable,因为它添加了peel_me()虚拟函数?(我假设答案必须是的)。如果是这样,编译器会提供Apple的实例另一个VPTR(即在其Fruit基类部分的顶部)?

)?
class Fruit {
  public:
    virtual void display();
};
class Apple : public Fruit {
  public:
    virtual void display() { std::cout << "I'm an apple!n"; }
    virtual void peel_me(); // extra virtual function, that is not in the base class
};

我似乎在任何地方都找不到答案。

通常:

Apple不管您是否添加 peel_me,都需要自己的vtable,因为它需要在Apple实例上通过虚拟呼叫找到其 display的覆盖。

添加peel_me使该VTable一个条目比其他条件更大 - 与peel_me的代码相比,此附加条目可能会或可能不会占用大量空间,但您可能期望不会。Apple的所有派生类别的VTABLES也比没有peel_me

Apple的实例具有单个VPTR。它指向Apple的VTable。该表包含Apple的所有虚拟成员函数的入口,包括从Fruit继承的选项,包括Apple中未覆盖的任何条件(在这种情况下,Apple中的VTable条目是指Fruit中的实现。

<</p> <</p> <</p> /div>

如果基类已经具有虚拟函数,则无。

仅在层次结构链中声明的第一个virtual函数会影响对象的大小,因为添加了指向虚拟表的指针。随后的没有。

这当然取决于实现,但大多数是这样的。

编译器通常会创建一个vtable来存储对象的虚拟函数。因此,添加一个通常的成本(假设基类已经具有虚拟函数,因此存储vtable的开销已经被支付了)存储了一个更多功能指针,以及对每个指针的速度影响致电该虚拟功能。

没有绝对规则,这取决于实现,但是...如果您的派生类已经超载至少一个基类中的虚拟功能,它已经有自己的 vtable;添加虚拟函数将增加一个条目vtable(通常为4或8个字节)。但是自从那里应该只是每个过程的VTable的一个实例,那就是整个程序中的一个指针,在现代机器上可以有效地认为什么都没有。