【问题标题】:When is VTable in C++ created?C++中的VTable是什么时候创建的?
【发布时间】:2011-04-20 10:54:08
【问题描述】:

我想知道 vtable 是什么时候创建的? 是在 main() 之前的启动代码中还是在其他时间点??

【问题讨论】:

    标签: c++


    【解决方案1】:

    vtable 不是 C++ 概念,因此是否使用它们以及何时创建它们将取决于实现。

    通常,vtables 是在编译时创建的结构(因为它们可以在编译时确定)。当在运行时创建特定类型的对象时,它们将具有一个 vptr,该对象将在构造时初始化为指向静态 vtable

    【讨论】:

    • 谢谢,但是我的一位导师告诉我,在调用主函数之前创建了一个 vtable。它是在 StartupCRT 代码期间创建的。我只是想确认并了解更多。
    • @Sen:也许,但也许不是。 C++ 实现不必使用 vtables,因此它们是否嵌入在二进制文件中、在启动代码中构建或在需要时(不太可能)动态分配完全取决于实现。无论实现选择做什么,都应该对程序透明,因此程序员知道使用虚函数会产生什么行为比在他使用的特定平台上如何实现虚函数更重要。
    • @Sen:StartupCRT 听起来很像微软特有的东西,他或她告诉你的可能对于微软的 Visual C++ 来说是正确的,但正如查尔斯所说,C++ 标准本身允许每个编译器供应商只要执行正确,就可以选择他们喜欢的任何实现。其他供应商可能甚至没有“StartupCRT”功能。
    • @user433534:是的,你是对的..我们正在接受培训,我们正在使用 Microsoft Visual C++ 2010..
    • @Sen:如果你也用vc++ 标记你的问题,它会有所帮助。从技术上讲,我也不认为这是真的。我相信它们是程序加载期间创建的,而 CRT 是在 之后 加载但 之前 main. 初始化的
    【解决方案2】:

    vtable 在编译时创建。当在运行时创建新对象时,隐藏的 vtable 指针被设置为指向 vtable。

    但请记住,在对象完全构造之前,如果虚函数无法可靠使用。 (构造函数中没有调用虚函数。)

    编辑 我想我会解决 cmets 中的问题。

    正如已经指出的,如何创建和使用 vtable 的确切细节由实现决定。 c++ 规范只提供了必须保证的特定行为,因此实现有很大的回旋余地。它根本不需要使用 vtables(尽管大多数都这样做)。一般来说,你不需要知道这些细节。您只需要知道,当您调用虚函数时,它会按照您的预期执行,而不管如何它是这样做的。

    也就是说,我将澄清有关典型实现的几点。具有虚函数的类有一个隐藏指针(我们称之为 vptr),它指向该类的 vtable。假设我们有一个员工类:

    class Employee {
    public:
      virtual work();
    };
    

    这个类的结构中会有一个 vptr,所以它实际上可能是这样的:

    class Employee {
    public:
      vtble *vptr;  // hidden pointer
      virtual work();
    };
    

    当我们从这个类派生时,它也会有一个 vptr,它必须在同一个位置(在这种情况下,在开头)。这样当一个函数被调用时,无论派生类的类型如何,它总是使用开头的 vptr 来找到正确的 vtable。

    【讨论】:

    • 严格来说,在构造函数中使用虚函数是可靠的。结果定义明确(纯虚函数除外),但通常不是所期望的。
    • 嗨 JoshD,您能否解释一下您告诉过的以下行:“在运行时创建新对象时,隐藏的 vtable 指针设置为指向 vtable。”作为初学者,我觉得很难理解。
    • Charles 是正确的,但实际上,对编译器的实际工作有一个普遍的期望并不是一件坏事——只要你不太依赖它——而且你的描述是现实的。 @Sen:如果你说Employee e,其中 Employee 是一个具有虚方法的类,那么新对象 e 通常具有编译器为指向 Employee 的 vtable 的指针保留的空间。如果将 President 派生自 Employee,那么它的 vtable 指针将指向 President vtable,但两个 vtable 指针相对于其他 Employee 数据成员的偏移量相同。
    • @user433534:能否请您扩展这一行“但两个 vtable 指针相对于其他 Employee 数据成员的偏移量相同”?
    • @Sen:如果我告诉你在地址 0x100 处有一个 Employee 对象,你可能会在偏移量 0x4,即 0x104 处找到 __vptr。如果 Employee 对象实际上是 President 对象,情况仍然如此。
    猜你喜欢
    • 2013-11-24
    • 2016-10-07
    • 2014-12-08
    • 1970-01-01
    • 2011-04-03
    • 2017-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多