不要對陣列使用多型

2021-06-07 04:53:20 字數 2412 閱讀 2550

不要對陣列使用多型

類繼承的最重要的特性是你可以通過基類指標或引用來操作派生類。這樣的指標或引用具有行為的多型性,就好像它們同時具有多種形態。c++允許你通過基類指標和引用來操作派生類陣列。不過這根本就不是乙個特性,因為這樣的**幾乎從不如你所願地那樣執行。

假設你有乙個類bst(比如是搜尋樹物件)和繼承自bst類的派生類balancedbst:

class

bst ;

class

balancedbst:

public

bst ;

有這樣乙個函式,它能列印出bst類陣列中每乙個bst物件的內容:

void

printbstarray(ostream

&s,

const

bst array,

intnumelements) //

過載了操作符<<

}

當你傳遞給該函式乙個含有bst物件的陣列變數時,它能夠正常執行:

bst bstarray[

10];

...printbstarray(cout, bstarray,

10);

//執行正常

然而,請考慮一下,當你把含有balancedbst物件的陣列變數傳遞給printbstarray函式時,會產生什麼樣的後果:

balancedbst bbstarray[

10];

...printbstarray(cout, bbstarray,

10);

//還會執行正常麼?

你的編譯器將會毫無警告地編譯這個函式,但是再看一下這個函式的迴圈**:

for

(inti =

0; i

<

numelements; )

這裡的array[i]只是乙個指標演算法的縮寫:它所代表的是*(array)。我們知道array是乙個指向陣列起始位址的指標,但是array中各元素記憶體位址與陣列的起始位址的間隔究竟有多大呢?它們的間隔是i*sizeof(乙個在陣列裡的物件),因為在array陣列[0]到[i]間有i個物件。編譯器為了建立正確遍歷陣列的執行**,它必須能夠確定陣列中物件的大小,這對編譯器來說是很容易做到的。引數array被宣告為bst型別,所以array陣列中每乙個元素都是bst型別,因此每個元素與陣列起始位址的間隔是i*sizeof(bst)。

至少你的編譯器是這麼認為的。但是如果你把乙個含有balancedbst物件的陣列變數傳遞給printbstarray函式,你的編譯器就會犯錯誤。在這種情況下,編譯器原先已經假設陣列中元素與bst物件的大小一致,但是現在陣列中每乙個物件大小卻與balancedbst一致。派生類的長度通常都比基類要長。我們料想balancedbst物件長度的比bst長。如果如此的話,printbstarray函式生成的指標演算法將是錯誤的,沒有人知道如果用balancedbst陣列來執行printbstarray函式將會發生什麼樣的後果。不論是什麼後果都是令人不愉快的。

如果你試圖刪除乙個含有派生類物件的陣列,將會發生各種各樣的問題。以下是一種你可能採用的但不正確的做法。

//

刪除乙個陣列, 但是首先記錄乙個刪除資訊

void

deletearray(ostream

&logstream, bst array)

balancedbst 

*baltreearray =//

建立乙個balancedbst物件陣列

newbalancedbst[

50];

...deletearray(cout, baltreearray);

//記錄這個刪除操作

這裡面也掩藏著你看不到的指標演算法。當乙個陣列被刪除時,每乙個陣列元素的析構函式也會被呼叫。當編譯器遇到這樣的**:

delete  array;
它肯定象這樣生成**:

//

以與構造順序相反的順序來

//解構array陣列裡的物件

for(

inti

=陣列元素的個數

1; i

>=0;

--i) //

析構函式

因為你所編寫的迴圈語句根本不能正確執行,所以當編譯成可執行**後,也不可能正常執行。語言規範中說通過乙個基類指標來刪除乙個含有派生類物件的陣列,結果將是不確定的。這實際意味著執行這樣的**肯定不會有什麼好結果。多型和指標演算法不能混合在一起來用,所以陣列與多型也不能用在一起。

值得注意的是如果你不從乙個具體類(concrete classes)(例如bst)派生出另乙個具體類(例如balancedbst),那麼你就不太可能犯這種使用多型性陣列的錯誤。

不要對陣列和指標運算使用多型

先看下面的程式 includeusing namespace std class animal animal char tmp virtual animal friend ostream operator display wtarray,3 將派生類陣列傳遞給display函式,陣列名退化為指標,即...

Item M3 不要對陣列使用多型 無責任書評

其實是 more effective c 書上的,並非原文照搬,而是刪減無關的內容,補充了一些事實和看法。類繼承的最重要的特性是你可以通過基類指標或引用來操作派生類。這樣的指標或引用具有行為的多型性,就好像它們同時具有多種形態。c 允許你通過基類指標和引用來操作派生類陣列。不過這根本就不是乙個特性,...

不要使用多型性陣列

類繼承的最重要的特性是你可以通過基類指標或引用來操作派生類。這樣的指標或引用具有行為的多型性,就好像它們同時具有多種形態。c 允許你通過基類指標和引用來操作派生類陣列。不過這根本就不是乙個特性,因為這樣的 根本無法如你所願地那樣執行。假設你有乙個類bst 比如是搜尋樹物件 和繼承自bst類的派生類b...