【发布时间】:2011-04-20 10:54:08
【问题描述】:
我想知道 vtable 是什么时候创建的? 是在 main() 之前的启动代码中还是在其他时间点??
【问题讨论】:
标签: c++
我想知道 vtable 是什么时候创建的? 是在 main() 之前的启动代码中还是在其他时间点??
【问题讨论】:
标签: c++
vtable 不是 C++ 概念,因此是否使用它们以及何时创建它们将取决于实现。
通常,vtables 是在编译时创建的结构(因为它们可以在编译时确定)。当在运行时创建特定类型的对象时,它们将具有一个 vptr,该对象将在构造时初始化为指向静态 vtable。
【讨论】:
vc++ 标记你的问题,它会有所帮助。从技术上讲,我也不认为这是真的。我相信它们是在程序加载期间创建的,而 CRT 是在 之后 加载但 之前 main. 初始化的
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。
【讨论】:
Employee e,其中 Employee 是一个具有虚方法的类,那么新对象 e 通常具有编译器为指向 Employee 的 vtable 的指针保留的空间。如果将 President 派生自 Employee,那么它的 vtable 指针将指向 President vtable,但两个 vtable 指针相对于其他 Employee 数据成员的偏移量相同。
__vptr。如果 Employee 对象实际上是 President 对象,情况仍然如此。