不要使用多型性陣列

2021-04-01 07:20:54 字數 2236 閱讀 7299

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

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

class bst ;

class balancedbst: public bst ;

在乙個真實的程式裡,這樣的類應該是模板類,但是在這個例子裡並不重要,加上模板只會使得**更難閱讀。為了便於討論,我們假設bst和balancedbst只包含int型別資料。

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

void printbstarray(ostream& s,

const bst array,

int numelements)

//過載了操作符<<

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

bst bstarray[10];

...printbstarray(cout, bstarray, 10);// 執行正常

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

balancedbst bbstarray[10];

...printbstarray(cout, bbstarray, 10);// 還會執行正常麼?

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

for (int i = 0; i < numelements; )

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

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

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

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

void deletearray(ostream& logstream, bst array)

balancedbst *baltreearray =// 建立乙個balancedbst物件陣列

new balancedbst[50];

...deletearray(cout, baltreearray);// 記錄這個刪除操作

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

delete array;

它肯定象這樣生成**:

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

// 解構array陣列裡的物件

for ( int i = 陣列元素的個數 1; i >= 0;--i)

// 析構函式

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

值得注意的是如果你不從乙個具體類(concrete classes)(例如bst)派生出另乙個具體類(例如balancedbst),那麼你就不太可能犯這種使用多型性陣列的錯誤。正如條款33所解釋的,不從具體類派生出具體類有很多好處。我希望你閱讀一下條款33的內容。

多型與多型性

1.什麼是多型 多型指的是同一種 類事物的不同形態 2.為何要用多型性 1 增加了程式的靈活性 2 增加了程式的可擴張性 多型性 分為靜態多型性和動態多型性 多型性 在多型的背景下,可以在不用考慮物件具體型別的前提下而直接使用物件 多型性的精髓 統一 3.如何用多型 class animal def...

this指標多型性

public class dervied extends base private string name dervied protected string id 2 public dervied public void tellname public void printname public s...

多型性定義

多型性就是多種表現形式,具體來說,可以用 乙個對外介面,多個內在實現方法 表示。舉乙個例子,計算機中的堆疊可以儲存各種格式的資料,包括整型,浮點或字元。不管儲存的是何種資料,堆疊的演算法實現是一樣的。針對不同的資料型別,程式設計人員不必手工選擇,只需使用統一介面名,系統可自動選擇。多型性也分靜態多型...