当我在派生类中添加额外的虚拟功能时,什么是开销
When I add an extra virtual function to a derived class, what is the overhead?
我正在通过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
中的实现。
如果基类已经具有虚拟函数,则无。
仅在层次结构链中声明的第一个virtual
函数会影响对象的大小,因为添加了指向虚拟表的指针。随后的没有。
这当然取决于实现,但大多数是这样的。
编译器通常会创建一个vtable
来存储对象的虚拟函数。因此,添加一个通常的成本(假设基类已经具有虚拟函数,因此存储vtable
的开销已经被支付了)存储了一个更多功能指针,以及对每个指针的速度影响致电该虚拟功能。
没有绝对规则,这取决于实现,但是...如果您的派生类已经超载至少一个基类中的虚拟功能,它已经有自己的 vtable
;添加虚拟函数将增加一个条目vtable
(通常为4或8个字节)。但是自从那里应该只是每个过程的VTable的一个实例,那就是整个程序中的一个指针,在现代机器上可以有效地认为什么都没有。
- 如何在C++中获得"静态纯虚拟"功能?
- std::is_trivially_copyable_v 关于虚拟功能
- 类似虚拟的朋友功能?
- 是否有任何模式等效于虚拟模板功能?
- 隐藏重载虚拟功能的模板化访客:SFINAE 在使用?
- 为什么我无法覆盖虚拟功能?
- 二叉搜索树 - 使用 Linux 在虚拟机中制作删除功能
- 虚拟功能不起作用
- 如果在创建对象时创建了 VPTR,那么为什么具有虚拟功能的类的大小在 32 位系统上为 4,在 64 位机器上为 8
- 虚拟功能如何影响static_cast?
- __declspec(属性)和虚拟功能
- 实现来自第三方类的虚拟功能
- 消除未使用的虚拟功能
- 为什么虚拟继承即使不涉及虚拟功能也需要 vtable?
- C 虚拟功能的输出
- 抽象类 A 由类 C 继承"through"类 B "intermediary"。如何声明虚拟功能?
- 虚拟功能是否不太可能导致堆栈溢出
- 使用继承和虚拟功能应用五个规则
- 父会员功能中虚拟函数的C 行为
- 在多态性中重新定义功能(虚拟),具有不同数量的参数