虚拟表 C++

发布于 2024-08-20 11:29:51 字数 444 浏览 28 评论 0原文

我读到很多人写“一个虚表存在于一个类中声明了虚函数”。

我的问题是,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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

难以启齿的温柔 2024-08-27 11:29:51

就仅考虑虚拟函数特定的功能而言,在 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 function print. Since Derived has its own version of print, the corresponding entry in Derived vtable is different from that in Base vtable. This would normally necessitate a separate vtable for Derived.

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 reused Base vtable for Derived as well. So, technically there wouldn't be any need for a separate vtable for Derived.

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.

魄砕の薆 2024-08-27 11:29:51

是的,你的理解是正确的。任何具有带有任何虚函数的基类的类都有一个虚函数表。

Yes, your understanding is correct. Any class that has a base with any virtual functions has a vtable.

柠北森屋 2024-08-27 11:29:51

是的,这是真的。实际上,给定 base 的定义:

class derived:public base{
public:
 void print(){cout<<"derived print\n";}
};

完全等同于:

class derived:public base{
public:
 virtual void print(){cout<<"derived print\n";}
};

... 因为您已经在 base 中将 print 定义为 virtual 。

我希望编译器能够强制执行...

Yes it's true. Actually, given base's defintion:

class derived:public base{
public:
 void print(){cout<<"derived print\n";}
};

is completely equivalent to:

class derived:public base{
public:
 virtual void print(){cout<<"derived print\n";}
};

... because you already defined print as virtual in base.

I'd wish the compiler would enforce that...

眉黛浅 2024-08-27 11:29:51

是的,确实如此。类从其基类继承所有数据成员,包括 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文