C 多重继承 - 编译器修改我的指针

c++ Multiple Inheritance - Compiler modifying my pointers

本文关键字:我的 指针 修改 编译器 多重继承      更新时间:2023-10-16

如果我运行以下代码,我会打印不同的地址。为什么?

class Base1 {
    int x;
};
class Base2 {
    int y;
};
class Derived : public Base1, public Base2 {
};
union U {
    Base2* b;
    Derived* d;
    U(Base2* b2) : b(b) {}
};
int main()
{
    Derived* d = new Derived;
    cout << d << "n";
    cout << U(d).d << "n";
    return 0;
}

更有趣的是,如果您反复进出联盟,地址会继续增加4个,例如

int main()
{
    Derived* d = new Derived;
    cout << d << "n";
    d = U(d).d;
    cout << d << "n";
    d = U(d).d;
    cout << d << "n";
    return 0;
}

如果工会被这样修改,那么问题就会消失

union U {
    void* v;
    Base2* b;
    Derived* d;
    U(void* v) : v(v) {}
};

另外,如果将任何一个基类都是空的,那么问题就会消失。这是编译器错误吗?我希望它让我的指针独自一人。

如果运行以下代码,我会收到不同的地址。为什么?

因为Derived对象的Base2子对象不是Derived对象的开始。因此地址不同。当编译器执行从Derived*Base2*的隐式铸件时,它需要调整地址。

给定Base1Base2类的定义,Derived类的两个子对象都不可能在Derived对象的起始地址上 - 两个子对象的该地址都没有空间。

说您有此代码:

Derived* d = new Derived;
Base1* pb1 = d;
Base2* pb2 = d;

pb1pb2如何指向相同的地址?pb1必须指向Base1::x项目,pb2必须指向Base2::y项目(这些项目必须不同)。

更有趣的是,如果您反复进出联盟,地址会继续增加4

因为您正在撰写b成员之后从工会的d成员阅读,这是不确定的行为(从本质上讲,您在Base2*上执行了类似reinterpret_cast<Derived*>()的内容)。

我希望它让我的指针独自一人。

如果您想要Base2*指针。多重继承使事情变得更加复杂 - 这就是为什么许多人建议避免使用它,除非绝对必要。

联合构造函数从不初始化成员d

联合构造函数有一个错误,其中它不是用参数B2初始化成员B,而是用自身初始化b

// b(b) should probably be b(b2)
U(Base2* b2) : b(b) {}

当您的第一个主要函数示例尝试构造u的实例并打印成员D时,它实际上是在打印未定义的值,因为成员d尚未初始化,并且不能保证可访问。

// U(d) doesn't construct member d, so .d returns an undefined value
cout << U(d).d << "n";

关于您的第二个主要功能示例

// d is set to a newly constructed instance of Derived
Derived* d = new Derived;
// current address of d is printed
cout << d << "n";
// a new instance of U is constructed. The address of member d will be in close
// proximity to the newly initialized U instance, and is what will be printed
d = U(d).d;
cout << d << "n";
// yet another new instance of U is constructed, and again, the address of member
// d will be in close proximity to the newly initialized U instance, and is
//what will be printed
d = U(d).d;
cout << d << "n";