【发布时间】:2019-03-13 19:12:50
【问题描述】:
我阅读了this question 和其他一些关于对象布局的内容,但我仍然不知道它的外观。
这是我的具体问题:
对于每个类(意味着如果我有 2 个超类,我将有 2 个指针),虚函数有 1 个vtable pointer。它在对象内部的什么位置?假设如下:class A{void virtual f(){}; int x;}; 对象A a 的地址是否与a.x 或a.f 的地址相同[或者可能指向默认方法,例如@987654329 @ 不正确,因为类方法未存储在对象中,如here 所解释的@]
例子:
class A{
int x;
void f(){}
void virtual g(){}
void virtual h(){}
};
A a;
std::cout << sizeof a; // result = 8
class A{
int x;
void f(){}
void virtual g(){}
};
A a;
std::cout << sizeof a; // result = 8
class A{
int x;
void f(){}
//void virtual g(){}
};
A a;
std::cout << sizeof a; // result = 4
从这些例子可以看出,当遇到一个数(n > 0)的虚函数时,一个指针(4字节,在我的32位机器上)被添加到对象中。会在其他数据成员之前添加吗?
将指向什么:
A a;
int *p = (int*)&a;
我用这个检查了它。从以下假设 vtable 指针总是在其他类成员之前是否正确?:
class A{
public:
A(int y){x=y;}
virtual void g(){}
int x;
virtual void f(){}
};
int main ()
{
A a(42);
int *p = (int*)&a;
std::cout << *p << std::endl; // = 4215116 (vtable address?)
std::cout << *(p+1) << std::endl; // = 42
return 0;
}
【问题讨论】:
-
@DanielLangr 是的,我编辑了我的 Q 并附上了一个答案的链接。忘了也删掉那句话。
-
@1201ProgramAlarm 确实是类似,但是那里的答案有些不清楚
-
@CIsForCookies: "从下面假设 vtable 指针总是在其他类成员之前是否正确?" 你甚至不能假设 vtables 是 存在在 C++ 实现中。当然,大多数编译器确实使用它们作为实现虚函数的手段。但不能保证这一点。
-
int *p = (int*)&a;如果A具有虚函数,我猜这是未定义的行为。您只能为 standard-layout classes 执行此操作。 -
@NicolBolas 所以基本上,在具有虚拟方法的类中,试图根据对象地址和偏移量查找特定成员注定要依赖于 UB 或至少依赖于实现?