簡體   English   中英

c ++多重繼承 - 編譯器修改我的指針

[英]c++ Multiple Inheritance - Compiler modifying my pointers

如果我運行以下代碼,我會打印不同的地址。 為什么?

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) {}
};

此外,如果任一基類都為空,則問題就會消失。 這是編譯器錯誤嗎? 我希望它能讓我的指針獨自一人。

如果我運行以下代碼,我會打印不同的地址。 為什么?

因為Base2中的子對象Derived的對象是不是在開始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成員后從union的d成員讀取,這是未定義的行為(你實際上在Base2*上執行類似reinterpret_cast<Derived*>()操作)。

我希望它能讓我的指針獨自一人。

如果你想要一個Base2*指針,那就沒有了。 多重繼承使事情變得更加復雜 - 這就是為什么許多人建議避免它,除非絕對必要。

union構造函數從不初始化成員d

union構造函數有一個bug,它不是用參數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";

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM