国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

More Effective C++:不使用多態(tài)性數(shù)組

2019-11-17 05:32:34
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  類繼續(xù)的最重要的特性是你可以通過(guò)基類指針或引用來(lái)操作派生類。這樣的指針或引用具有行為的多態(tài)性,就似乎它們同時(shí)具有多種形態(tài)。C++答應(yīng)你通過(guò)基類指針和引用來(lái)操作派生類數(shù)組。不過(guò)這根本就不是一個(gè)特性,因?yàn)檫@樣的代碼根本無(wú)法如你所愿地那樣運(yùn)行。

  假設(shè)你有一個(gè)類BST(比如是搜索樹(shù)對(duì)象)和繼續(xù)自BST類的派生類BalancedBST:

class BST { ... };
class BalancedBST: public BST { ... };
  在一個(gè)真實(shí)的程序里,這樣的類應(yīng)該是模板類,但是在這個(gè)例子里并不重要,加上模板只會(huì)使得代碼更難閱讀。為了便于討論,我們假設(shè)BST和BalancedBST只包含int類型數(shù)據(jù)。

  有這樣一個(gè)函數(shù),它能打印出BST類數(shù)組中每一個(gè)BST對(duì)象的內(nèi)容:

void PRintBSTArray(ostream& s,
const BST array[],
int numElements)
{
 for (int i = 0; i < numElements; ) {
  s << array[i]; //假設(shè)BST類
 } //重載了操作符<<
}
  當(dāng)你傳遞給該函數(shù)一個(gè)含有BST對(duì)象的數(shù)組變量時(shí),它能夠正常運(yùn)行:

BST BSTArray[10];
...
printBSTArray(cout, BSTArray, 10); // 運(yùn)行正常
  然而,請(qǐng)考慮一下,當(dāng)你把含有BalancedBST對(duì)象的數(shù)組變量傳遞給printBSTArray函數(shù)時(shí),會(huì)產(chǎn)生什么樣的后果:

BalancedBST bBSTArray[10];
...
printBSTArray(cout, bBSTArray, 10); // 還會(huì)運(yùn)行正常么?
  你的編譯器將會(huì)毫無(wú)警告地編譯這個(gè)函數(shù),但是再看一下這個(gè)函數(shù)的循環(huán)代碼:

for (int i = 0; i < numElements; ) {
 s << array[i];
}
  這里的array[I]只是一個(gè)指針?biāo)惴ǖ目s寫(xiě):它所代表的是*(array)。我們知道array是一個(gè)指向數(shù)組起始地址的指針,但是array中各元素內(nèi)存地址與數(shù)組的起始地址的間隔究竟有多大呢?它們的間隔是i*sizeof(一個(gè)在數(shù)組里的對(duì)象),因?yàn)樵赼rray數(shù)組[0]到[I]間有I個(gè)對(duì)象。編譯器為了建立正確遍歷數(shù)組的執(zhí)行代碼,它必須能夠確定數(shù)組中對(duì)象的大小,這對(duì)編譯器來(lái)說(shuō)是很輕易做到的。參數(shù)array被聲明為BST類型,所以array數(shù)組中每一個(gè)元素都是BST類型,因此每個(gè)元素與數(shù)組起始地址的間隔是be i*sizeof(BST)。

  至少你的編譯器是這么認(rèn)為的。但是假如你把一個(gè)含有BalancedBST對(duì)象的數(shù)組變量傳遞給printBSTArray函數(shù),你的編譯器就會(huì)犯錯(cuò)誤。在這種情況下,編譯器原先已經(jīng)假設(shè)數(shù)組中元素與BST對(duì)象的大小一致,但是現(xiàn)在數(shù)組中每一個(gè)對(duì)象大小卻與BalancedBST一致。派生類的長(zhǎng)度通常都比基類要長(zhǎng)。我們料想BalancedBST對(duì)象長(zhǎng)度的比BST長(zhǎng)。假如如此的話,printBSTArray函數(shù)生成的指針?biāo)惴▽⑹清e(cuò)誤的,沒(méi)有人知道假如用BalancedBST數(shù)組來(lái)執(zhí)行printBSTArray函數(shù)將會(huì)發(fā)生什么樣的后果。不論是什么后果都是令人不愉快的。

  假如你試圖刪除一個(gè)含有派生類對(duì)象的數(shù)組,將會(huì)發(fā)生各種各樣的問(wèn)題。以下是一種你可能的不正確的做法。

//刪除一個(gè)數(shù)組, 但是首先記錄一個(gè)刪除信息
void deleteArray(ostream& logStream, BST array[])
{
 logStream << "Deleting array at address "
 << static_cast(array) << '/n';
 delete [] array;
}
BalancedBST *balTreeArray = // 建立一個(gè)BalancedBST對(duì)象數(shù)組
new BalancedBST[50];
...
deleteArray(cout, balTreeArray); // 記錄這個(gè)刪除操作
  這里面也掩藏著你看不到的指針?biāo)惴ā.?dāng)一個(gè)數(shù)組被刪除時(shí),每一個(gè)數(shù)組元素的析構(gòu)函數(shù)也會(huì)被調(diào)用。當(dāng)編譯器碰到這樣的代碼:

delete [] array;
  它肯定象這樣生成代碼:

// 以與構(gòu)造順序相反的順序來(lái)
// 解構(gòu)array數(shù)組里的對(duì)象
for ( int i = 數(shù)組元素的個(gè)數(shù) 1; i >= 0;--i)
{
 array[i].BST::~BST(); // 調(diào)用 array[i]的
} // 析構(gòu)函數(shù)
  因?yàn)槟闼帉?xiě)的循環(huán)語(yǔ)句根本不能正運(yùn)行,所以當(dāng)編譯成可執(zhí)行代碼后,也不可能正常運(yùn)行。語(yǔ)言規(guī)范中說(shuō)通過(guò)一個(gè)基類指針來(lái)刪除一個(gè)含有派生類對(duì)象的數(shù)組,結(jié)果將是不確定的。這實(shí)際意味著執(zhí)行這樣的代碼肯定不會(huì)有什么好結(jié)果。多態(tài)和指針?biāo)惴ú荒芑旌显谝黄饋?lái)用,所以數(shù)組與多態(tài)也不能用在一起。

  值得注重的是假如你不從一個(gè)具體類(concrete classes)(例如BST)派生出另一個(gè)具體類(例如BalancedBST),那么你就不太可能犯這種使用多態(tài)性數(shù)組的錯(cuò)誤。正如我在后面將介紹的條款33所解釋的,不從具體類派生出具體類有很多好處。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 峨眉山市| 安陆市| 长顺县| 龙州县| 交口县| 威宁| 哈密市| 广汉市| 兴业县| 饶阳县| 萍乡市| 广东省| 寿宁县| 九寨沟县| 石棉县| 施秉县| 天等县| 屏山县| 蓬安县| 仲巴县| 景洪市| 友谊县| 邯郸市| 玛多县| 灵宝市| 柏乡县| 醴陵市| 遵化市| 池州市| 白河县| 隆林| 柳河县| 佛冈县| 张家界市| 沙田区| 垫江县| 慈溪市| 林芝县| 科技| 辽宁省| 永济市|