【问题标题】:Multiple Inheritance: Different Address same address多重继承:不同地址相同地址
【发布时间】:2015-09-21 03:35:16
【问题描述】:

我已经编写了一个示例程序。 如果我打印 pa 和 pb 的地址,两者都是不同的。 你能告诉我为什么会这样吗?

#include<iostream>
using namespace std;
class A {
int x;
};

class B {
int y;
};

class C: public A, public B {
int z;
};

int main()
{
 C c;
 A *pa;
 B *pb;

 pa = &c;
 pb = &c;

cout<<pa<<endl;
cout<<pb<<endl;

}

【问题讨论】:

  • 为什么地址不能不同? papb 指向不同的对象!
  • @JonathonReinhart:这与int n = 1.5; 存在相同的心理障碍,就像A*不能表达指向C的概念一样。

标签: c++


【解决方案1】:

正如Kerrek SB 所说,您的示例中的papb 实际上并不指向c,而是指向@987654326 的AB 子对象 @。

使用多重继承,来自基类的数据本质上是一个接一个堆叠。基类型指针只是偏移到该基类的数据。因此,papb 指向c 的不同偏移量。

#include<iostream>
using namespace std;

class A {
    public:
    int x;
};

class B {
    public:
    int y;
};

class C: public A, public B {
    public:
    int z;
};

int main()
{
    C c;
    cout << "    &c: " << &c << endl << endl;

    cout << "(A*)&c: " << (A*)&c << endl;
    cout << "(B*)&c: " << (B*)&c << endl << endl;

    cout << "  &c.x: " << &c.x << endl;
    cout << "  &c.y: " << &c.y << endl;
    cout << "  &c.z: " << &c.z << endl << endl;
}

结果:

    &c: 0x7ffdfeb26b20

(A*)&c: 0x7ffdfeb26b20
(B*)&c: 0x7ffdfeb26b24

  &c.x: 0x7ffdfeb26b20
  &c.y: 0x7ffdfeb26b24
  &c.z: 0x7ffdfeb26b28

所以你可以看到C的布局是这样的:

                  ---------------
0x7ffdfeb26b20    |     x       |     class A data
                  ---------------
0x7ffdfeb26b24    |     y       |     class B data
                  ---------------
0x7ffdfeb26b28    |     z       |     class C data
                  ---------------

如果您在此示例中添加一些虚拟方法,您会发现子类 vtable 也会发生同样的事情。

【讨论】:

    【解决方案2】:
        ---------   <------pa = &c
       |    x    |
        ---------   <------pb = &c
       |    y    |
        ---------
       |    z    |
        ---------
    

    取决于类的内存模型,上面是C类在内存中的对象

    【讨论】:

      【解决方案3】:

      回到纯 c 的美好时光,只有结构。

      struct Base{
         int baseMember;
      }
      
      struct Child{
         struct Base parent;
         int someMoreMembers;
      }
      

      这样,取消引用指向Child 的指针就好像它是基指针一样,将产生指向Base 的完美指针,因为它是第一个成员。 在 c++ 中,这仍然以相同的方式工作(通常)。但是,如果您现在继承两个类,则不能将它们都作为结构中的第一个成员。因此,C++ 通过添加特定基础数据所在的偏移量,将指向基址的指针转换为指向子代的指针。

      【讨论】:

        猜你喜欢
        • 2012-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-24
        • 2011-04-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多