虚拟表 C++
我读到很多人写“一个虚表存在于一个类中声明了虚函数”。
我的问题是,vtable 只存在于具有虚函数的类中,还是也存在于从该类派生的类中。
例如
class Base{
public:
virtual void print(){cout<<"Base Print\n";}
};
class Derived:public Base{
public:
void print(){cout<<"Derived print\n";}
};
//From main.cpp
Base* b = new Derived;
b->print();
问题:如果派生类没有 vtable,那么输出就不会是“派生打印”。因此,在我看来,任何声明了虚函数的类以及从该类继承的类中都存在一个虚函数表。这是正确的吗?
I read a lot of people writing "a virtual table exists for a class that has a virtual function declared in it".
My question is, does a vtable exists only for a class that has a virtual function or does it also exist for classes derived from that class.
e.g
class Base{
public:
virtual void print(){cout<<"Base Print\n";}
};
class Derived:public Base{
public:
void print(){cout<<"Derived print\n";}
};
//From main.cpp
Base* b = new Derived;
b->print();
Question: Had there been no vtable for class derived then the output would not have been "derived print". So IMO there exists a vtable for any class that has virtual function declared and also in classes inheriting from that class. Is this correct ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
就仅考虑虚拟函数特定的功能而言,在 vtable 实现的传统方法中,当且仅当派生类重写至少一个虚拟函数时,派生类才需要 vtable 的单独版本。在您的示例中,
Derived
覆盖虚拟函数print
。由于Derived
有自己的print
版本,因此Derived
vtable 中的相应条目与Base
vtable 中的条目不同。这通常需要为Derived
提供一个单独的 vtable。如果
Derived
根本没有重写任何内容,形式上它仍然是一个单独的多态类,但为了使其虚拟函数正常工作,我们可以简单地重用Base
Derived
的 vtable 也是如此。因此,从技术上讲,Derived
不需要单独的 vtable。然而,在实际实现中,我们通常称为“vtable”的数据结构通常还包含一些附加的特定于类的信息。这些额外的信息是如此特定于类的,以至于大多数时候不可能在层次结构中的不同类之间共享 vtable,即使它们使用相同的虚拟函数集。例如,在一些实现中,存储在每个多态对象中的虚函数表指针指向还存储关于该类的所谓“RTTI信息”的数据结构。因此,在大多数(如果不是全部)实际实现中,每个多态类都有自己的 vtable,即使存储在这些表中的虚拟函数指针恰好相同。
As far as only virtual-function-specific functionality is considered, in a traditional approach to vtable implementation derived class would need a separate version of vtable if and only if that derived class overrides at least one virtual function. In your example,
Derived
overrides virtual functionprint
. SinceDerived
has its own version ofprint
, the corresponding entry inDerived
vtable is different from that inBase
vtable. This would normally necessitate a separate vtable forDerived
.If
Derived
didn't override anything at all, formally it still would be a separate polymorphic class, but in order to make its virtual functions work properly we could have simply reusedBase
vtable forDerived
as well. So, technically there wouldn't be any need for a separate vtable forDerived
.However, in practical implementations, the data structure that we usually refer to as "vtable", often holds some additional class-specific information as well. That extra information is so class-specific that most of the time it becomes impossible to share vtables between different classes in hierarchy, even if they use the same set of virtual functions. For example, in some implementations the vtable pointer stored in each polymorphic object points to data structure that also stores so called "RTTI information" about the class. For this reason, in most (if not all) practical implementations each polymorphic class gets its own vtable, even if the virtual function pointers stored in those tables happen to be the same.
是的,你的理解是正确的。任何具有带有任何虚函数的基类的类都有一个虚函数表。
Yes, your understanding is correct. Any class that has a base with any virtual functions has a vtable.
是的,这是真的。实际上,给定 base 的定义:
完全等同于:
... 因为您已经在 base 中将 print 定义为 virtual 。
我希望编译器能够强制执行...
Yes it's true. Actually, given base's defintion:
is completely equivalent to:
... because you already defined print as virtual in base.
I'd wish the compiler would enforce that...
是的,确实如此。类从其基类继承所有数据成员,包括 vtable。但是,vtable 条目会相应调整(例如,如果类重写基类虚拟方法,则 vtable 中的相应条目必须指向其自己的实现)。
但请记住,“vtable”的概念是几乎每个编译器都使用的常见做法,但它不是强制性的,也不是标准化的。
Yes, that's true. A class inherits all data members from its base class, including the vtable. However, vtable entries are adjusted accordingly (for example if the class overrides a base class virtual method, the corresponding entry in the vtable must point to its own implementation).
But keep in mind that the concept of a 'vtable' is common practice used by vitually every compiler, but it is not compulsory nor standardized.