2015-05-08 83 views
2

考慮這個例子:這是爲什麼這樣工作? (多重繼承,切片)

#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    int x; 
}; 

class B 
{ 
public: 
    int y; 
    B() { y = 0; } 
    B(int var): y(var) {} 
}; 

class C : public A, public B 
{ 
public: 
    void assignB(B x) 
    { 
     *(B *)this = x; // <-- why does this properly assign B? 
    } 
}; 

int main() { 
    C test; 
    test.x = 5; 
    test.y = 10; 
    test.assignB(B(2)); 
    cout << "x " << test.x << endl; 
    cout << "y " << test.y << endl; 
    return 0; 
} 

我很好奇的是C類 通常的assignB方法,我會期望類型轉換的是,(B *) this將強制轉換thisB*,因此覆蓋x成員,而不是y。但是,這段代碼完全相反:它正確地使用了分配給C的B部分。

剛剛在MSVC 2013和GCC 4.9.2上進行了測試。兩者的表現都一樣。

+0

這是一個'static_cast',它足夠聰明,可以執行必要的指針調整。你預計會發生什麼演員? 'reinterpret_cast'? –

+0

可能吧,是的。我發現它很好奇,因爲C-stlye的鑄造通常表現得如此。 – velis

回答

2

這是因爲指針因多重繼承而被調整。

如果打印的地址,這將是顯而易見的

cout << (long long int)(this) << endl; 
cout << (long long int)((B *)this) << endl; 

還要考慮使用的static_cast。在這種情況下,純C風格的演員也可以工作。

+0

那麼C++標準定義了這種行爲?我知道打印地址會顯示我發現的內容。我只是好奇,爲什麼這是有效的。 – velis

+0

@velis你不想讓它工作嗎?你還會怎麼引用一個乘法繼承類的一部分...... 假設你需要將指向類型C的對象的指針傳遞給一個只接受指向類型B對象的指針的函數 - 那該如何工作? C也是B(如果繼承是公共的,至少它是部分)所以它應該是可能的 – onqtam

+0

是的,我希望它能夠工作。但是,像這樣的C風格的轉換通常會執行reinterpret_cast。這就是我問的原因。 – velis