C++ 中的虚拟表和虚拟指针的数量程序
假设我们有以下程序:
class A
{ public:
virtual fun(){};
};
class B:public A
{ public:
virtual fun(){};
};
int main()
{
A a1;
B b1;
}
我的问题是,当我们运行该程序时,将创建多少个 vtables 和多少个 vptrs ?
Let say we have below program:
class A
{ public:
virtual fun(){};
};
class B:public A
{ public:
virtual fun(){};
};
int main()
{
A a1;
B b1;
}
My question is how many vtables
and how many vptrs
will be created, when we run this program?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
它严重依赖于实现,但通常每个具有任何虚函数的类都会获得一个 vtable 对象(没有虚函数或基类的类不需要它们),并且具有 vtable 的类的每个对象都会获得一个 vptr (指向类的 vtable)。
如果您有多个继承和虚拟基类,事情会变得更加复杂——可以通过多种方式实现。一些实现为每个附加基类使用一个附加虚函数表(因此最终每个类的每个基类都有一个虚函数表),而其他实现则使用一个包含额外信息的虚函数表。这可能会导致每个对象需要多个 vptr。
B 中的
virtual
关键字是无关紧要的——如果该函数在基类中是虚拟的,则无论如何它在派生类中也将是虚拟的。Its heavily implementation dependent, but generally you'll get one vtable object per class that has any virtual functions (classes with no virtual functions or bases don't need them), and one vptr per object of a class with a vtable (pointing at the class's vtable).
Things get more complex if you have multiple inheritance and virtual base classes -- which can be implemented many ways. Some implementations use an addition vtable per additional base class (so you end up with a vtable per base class per class), while others use a single vtable with extra info in it. This may result in needing multiple vptrs per object.
The
virtual
keyword in B is irrelevant -- if the function is virtual in the base class, it will be virtual in the derived classes regardless.该程序可以优化为与此程序完全相同:
因此,“无”是一种可能性。
This program can be optimized to be exactly like this one:
So, "none" is a possibility.
基本上,2. 1 个用于
class A
,1 个用于class B
(vftables) 和 2 个 vfptrs,1 个用于a1
,1 个用于b1。
但是,这不是标准强制要求,因此您也可以不这样做。 (通常实现使用 vftables,但它不是强制的。
注意 @R.Martinho Fernandes,启用优化后,您将不会创建任何对象,因此没有
vfptrs
。Basically, 2. One for
class A
, one forclass B
(vftables) and 2 vfptrs, one fora1
and one forb1
.However, this is not standard mandated, so you could as well have none. (usually implementations use vftables, but its not mandated.
Note @R. Martinho Fernandes with optimizations on, you will have no objects created, so no
vfptrs
.请注意,这严格依赖于实现。
C++ 标准没有提及
vptr
或vtable
,虚拟机制作为编译器的实现细节被忽略。因此,实际上,编译器可以在不使用vptr
或vtable
的情况下实现它。但是,几乎所有已知的编译器都使用vptr
和vtable< 来实现它。 /代码>。
鉴于上述情况,回答您的问题:
每个类都有自己的虚拟表。
而每个对象都有自己的虚拟指针。
Note that this is strictly implementation dependent.
C++ Standard does not talk of
vptr
orvtable
, the virtual mechanism is left out as an implementation detail for compilers. So practically, compilers can implement it without usingvptr
orvtable
.However, almost all known compilers implement it usingvptr
andvtable
.Given the above, to answer your question:
Each class will have its own virtual table.
While each object has its own virtual pointer.
仅当基类中至少有 1 个虚拟函数时才会创建虚拟表,该虚拟函数将以任何方式继承到派生类。即使您从派生类 B 中删除 virtual 关键字也没关系,因为您已经在 A 中拥有了 virtual fun() 。
因此,虚拟表的数量将为 2(作为其每个类的基础),虚拟指针的数量也将为 2,作为其每个对象的基础。 A---v_ptr* 、 A::fun()
和 A::fun() 的 VTABLE B 的 VTABLE--- V_ptr*(继承自 A),B::fun()/* B 可以访问 A::fun 和 A::fun()/* B 可以访问 A::fun 和 A::fun()。 B 的 fun(),但由于我们提到 A::fun() 作为虚拟 B 的虚拟表充满了该函数的最派生版本 fun(),它只不过是 B::fun()。希望这能消除您的疑虑,
Virual table will be created only if at least 1 virtual function is there in the Base class, which will be any way inherited to the derived classes. It doesn't matter even if you remove virtual keyword from derived class B because already u are having a virtual fun() in A.
So the number of virtual tables will be 2 (as its per class basis) and number of virtual ptrs will also be 2, as its per object basis. VTABLE for A---v_ptr* , A::fun()
& VTABLE for B--- V_ptr*(which was inherited from A),B::fun()/* B have access to both A::fun & B's fun(), but since we mentioned A::fun() as virtual B's virtual table is filled with the most derived version of the function, fun(), which is nothing but B::fun(). Hope this clears your doubt,
将有 2 个
vtable
,一个用于A 类,一个用于B 类。并且会有3个vptr
,一个在a1中,两个在b1中(一个指向A类的vtable
,另一个指向B 类的 vtable
)。There will be 2
vtables
, one for class A and one for class B. And there will be 3vptrs
, one in a1 and two in b1(one pointing tovtable
of class A and other pointing tovtable
of class B).