成员函数调用和 C++ 对象模型

Member Function Call and the C++ Object Model

考虑以下代码,旨在研究如何进行成员函数调用以及它与 C++ 的对象模型的关系:

struct A {
  int a_;
};
struct B : A {
  int b_;
  void f();
};
void B::f() {
  std::cout << "this\t" << std::hex << this << '\n';
}
struct C: B {
  int c_;
};
int main()
{
  C c;
  C* pc = &c;
  std::cout << "&c\t" << std::hex << pc << '\n';
  pc->f();
  return 0;
}

基于 C++ 对象模型,对象 c 将具有对象布局:

  -------
 | a_    |
 |------ |
 | b_    |
 |------ |
 | c_    |
  -------

并且,

  1. B::f() 将被翻译成 void f(B *const)
  2. pc->f() 会被翻译成 void f(pc + offset(b_)),其中 offset(b_) 表示子对象 Bc.
  3. 中的偏移量

所以,根据以上观察,输出应该是:

&c     address_of_c
this   address_of_c + sizeof(a_) = address_of_c + 4

但我得到的是两者的相同地址(我使用的是 g++ 9.2):

&c      0xffffcc0c
this    0xffffcc0c

我不清楚为什么?有人可以解释一下吗?

仅供参考:Bjarne Stroustrup 有一篇关于此的文章;更具体的,你可以参考第4.2节(第373页):

https://www.usenix.org/legacy/publications/compsystems/1989/fall_stroustrup.pdf

谢谢!

Class C只继承了一个class B。所以你有

struct B
   ^
   |
   |
struct C

当创建class C 的对象时,class B 的子对象被放置在为class C 的对象分配的内存的开头.

在 class B 的对象中有一个 class A 的子对象。

你可以想象一下 class C 的对象的放置方式

struct B b;
int c_;