2014-01-16 36 views
1
class a 
{ 
    int var; 
} 
class b :public a 
{ 
    int var2,var3; 
} 

int main() 
{ 
    a *poi; 
    poi=new b; 
    //b *poi2; 
    //poi2=new a; 
    return 0 
} 

在上面的代碼中,我能夠使用指向基類指針變量的派生類類型分配內存。 即a *poi=new b; 但我無法使用指向派生類指針的基類類型分配內存。 即b *poi=new a;爲什麼我不能使用指向派生類指針的基類類型分配內存?

爲什麼下面的內存分配是不可能的? 它背後的邏輯是什麼?

+0

如果您有一個指向'b'對象的指針,則該對象不應該是一半構造的。 – chris

+3

想一想:如果'b * poi = new a;'是合法的,那麼'poi-> var2 ++;'應該做什麼? – Angew

回答

2

這實際上與內存分配沒有任何關係。這僅僅是在第一轉換是有效的隱式轉換(從派生的類指針指向基址指針),但第二個是不(從基類指針到派生指針):

§4.10/ 3 [CONV .ptr]類型爲「指向cv D的指針」(其中D是類類型)的值可以轉換爲類型爲「指向cv B的指針」的prvalue,其中B是D的基類(第10章)。

原因是多態性代表is-a關係。 A ba,但a不是b。因此,您可以讓a指針指向b,因爲它指向的對象是有效的a對象。但是,您不能讓b指針指向a,因爲a對象不一定是有效的b對象。

+0

好吧,它也與內存分配有關,因爲'sizeof(b)> sizeof(a)'。因此,通過分配「錯誤的方式」,當讀取'a2'對象末尾的'var2'或'var3'時,通過「合法」訪問未分配的內存來調用UB。 – Damon

+0

@Damon雖然分配不是「錯誤的方式」 - 這是轉換。如果允許轉換,UB只會在您嘗試訪問該對象時啓動。 –

4

這不是關於內存分配,而是關於繼承。

Fruit* f = new Apple 

運作良好,但

Apple* a = new Fruit 

會給你一個不完整的蘋果,甚至是一根香蕉,所以編譯器不允許你這樣做。

兩個指針具有相同的大小,你可以使用一個unsafe static cast到水果指針存儲到蘋果的指針,但是你應該避免這樣做

+0

它只是一個指針,只能存放地址......所以我們不需要打擾不完整的蘋果或香蕉......它只是指出了該課程的地址。 –

+0

是的,這兩個變量將只保存一個指針,一個'sizeof(f)== sizeof(a)',通常是8或4 –

+0

這就是要求「sizeof(f)== sizeof(a)」。那麼爲什麼我們不能映射到蘋果,香蕉甚至水果。這是可能的吶..是標準說的關於它。 –

1

這裏a *poi;poi=new b;是有效的,因爲poivar和參考由於繼承,b的對象也具有變量var。這是一個有效的參考。

b *poi2;poi2=new a;poi2也情況下可以具有var2var3a對象引用不包含var2var3。這導致無效的參考。 我的意思是poi2->var2是一個有效的陳述,但沒有var2如果編譯器允許poi2=new a;然後poi2->var2將指向一個無效的內存段。

相關問題