我正在阅读《C++ 对象模型内部》一书。书中有一个例子:
struct Base1
{
int v1;
};
struct Base2
{
int v2;
};
class Derived : public Base1, public Base2 {};
printf("&Derived::v1 = %p\n", &Derived::v1); // Print 0 in VS2008/VS2012
printf("&Derived::v2 = %p\n", &Derived::v2); // Print 0 in VS2008/VS2012
在前面的代码中,地址 Derived::v1 和 Derived::v2 的打印都将为0。但是,如果通过变量打印相同的地址:
int Derived::*p;
p = &Derived::v1;
printf("p = %p (&Derived::v1)\n", p); // Print 0 in VS2008/VS2012 as before
p = &Derived::v2;
printf("p = %p (&Derived::v2)\n", p); // Print 4 in VS2008/VS2012
通过检查 &Derived::v1 和 p 的大小,我得到 4。
// Both are 4
printf("Size of (&Derived::v1) is %d\n", sizeof(&Derived::v1));
printf("Size of p is %d\n", sizeof(p));
Derived::v1 的地址为0,但 Derived::v2 的地址为4。我不明白为什么 &Derived::v2在将其分配给变量时变为4 。
查看汇编代码,直接查询 Derived::v2 的地址时,翻译为0;但是当将其分配给变量时,它会被转换为4。
我在 VS2008 和 VS2012 上都测试过,结果是一样的。所以我认为微软选择这样的设计肯定是有原因的。
而且,如果你这样做:
d1.*(&Derived::v2) = 1;
显然&Derived::v2不是0。为什么编译器要区分这两种情况?
谁能告诉背后发生的事情?谢谢!
- 编辑 -
对于那些认为 &Derived::v1 没有得到有效地址的人。你从来没有这样做过吗?
Derived d1, d2;
d1.*p = 1;
d2.*p = 1;