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

C++ 成员函数调用和C++;对象模型,c++,class,inheritance,this,C++,Class,Inheritance,This,考虑以下代码,这些代码旨在研究成员函数调用的方式以及它与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* p

考虑以下代码,这些代码旨在研究成员函数调用的方式以及它与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;
}
以及

  • B::f()
    将被转换为
    void f(B*const)
  • pc->f()
    将转换为
    void f(pc+offset(b_))
    ,其中
    offset(b_)
    表示
    c
    中子对象
    b
    的偏移量
  • 因此,根据上述观察结果,输出应为:

    &c     address_of_c
    this   address_of_c + sizeof(a_) = address_of_c + 4
    
    但我得到的是两者的相同地址(我使用的是g++9.2):

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

    仅供参考:比亚恩·斯特劳斯特鲁普写了一篇关于这方面的文章;更具体地说,您可以参考第4.2节(第373页):


    谢谢

    类C只继承一个类B。因此

    struct B
       ^
       |
       |
    struct C
    
    创建类C的对象时,类B的子对象被放置在为类C的对象分配的内存的开头

    在B类的对象中有a类的子对象

    您可以想象C类对象的放置方式如下

    struct B b;
    int c_;
    

    为什么您认为它应该是
    pc+offset(b)
    而不是
    pc+offset(b)
    ,即
    C
    b
    子对象的偏移?如果查看图形,您可以看到
    A
    B
    子对象都从顶部开始,与
    C
    对象的地址相同。请注意,链接中的示例不同。它允许
    C
    A
    B
    继承。C中B子对象的偏移量是[u C+sizeof(A_u)=地址[u of_C+4=偏移量(B_u)。在比亚恩的例子中,C从A和B继承。但这有什么关系呢?在你的例子中,
    A
    子对象是
    B
    子对象的一部分,因此
    B
    子对象以
    a_
    开头,而不是以
    B_
    开头。在比亚恩的例子中,情况并非如此,
    A
    B
    子对象是
    C
    的不同部分。
    struct B
       ^
       |
       |
    struct C
    
    struct B b;
    int c_;