面向?qū)ο缶幊?/h1>
Inheritance繼承 Composition復(fù)合 Delegation委托
Composition(復(fù)合) 表示 has a
- Container -> Component
構(gòu)造由內(nèi)而外進(jìn)行,Container的構(gòu)造函數(shù)首先調(diào)用Component的default構(gòu)造函數(shù),然后才執(zhí)行自己。(即由編譯器默認(rèn)再初始化列表中調(diào)用Component的構(gòu)造函數(shù))
Container::Container(...):Component(){...}
析構(gòu)由外而內(nèi),Container的析構(gòu)函數(shù)先執(zhí)行自己,然后在調(diào)用Component的析構(gòu)函數(shù)(即由編譯器默認(rèn)在Container的析構(gòu)函數(shù)的最后調(diào)用Component的析構(gòu)函數(shù))
Container::~Container(...){... ~Component(); }
Delegation(委托).Composition by reference.Handle/Body模式(編譯防火墻模式)
- 在類內(nèi)有一個(gè)指向具體實(shí)現(xiàn)類的指針,類只提供一個(gè)調(diào)用的接口而不負(fù)責(zé)具體實(shí)現(xiàn),這樣可以通過讓指針指向不同的具體實(shí)現(xiàn)類來改變具體實(shí)現(xiàn)而不用影響客戶端,也不用全部重新編譯。
Inheritance(繼承),表示Is a
- Derived -> Base
構(gòu)造由內(nèi)而外進(jìn)行,Derived的構(gòu)造函數(shù)首先調(diào)用Base的default構(gòu)造函數(shù),然后才執(zhí)行自己。(即由編譯器默認(rèn)再初始化列表中調(diào)用Base的構(gòu)造函數(shù))
Derived::Derived(...):Base(){...}
析構(gòu)由外而內(nèi),Container的析構(gòu)函數(shù)先執(zhí)行自己,然后在調(diào)用Base的析構(gòu)函數(shù)(即由編譯器默認(rèn)在Derived的析構(gòu)函數(shù)的最后調(diào)用Base的析構(gòu)函數(shù))
Derived::~Derived(...){... ~Base(); }
base class的dtor必須是virtual,否則會(huì)出現(xiàn)undefined behavior
繼承應(yīng)配合virtual函數(shù)來使用。
如果函數(shù)沒有使用關(guān)鍵字virtual修飾,則程序?qū)⒏鶕?jù)對象、引用類型或指針類型調(diào)用函數(shù)。如果使用virtual修飾函數(shù)則程序?qū)⒏鶕?jù)引用或者指針 指向的對象類型 進(jìn)行選擇方法。但是將函數(shù)定義成virtual會(huì)增加程序的空間和時(shí)間開銷。在基類方法的聲明中使用關(guān)鍵字virtual可是該方法在基類以及所有的派生類(包括從派生類派生出來的類)中是虛的。
- 為基類聲明一個(gè)虛析構(gòu)函數(shù)是一種慣例(除非它不做基類),這樣可以確保釋放派生對象時(shí)按正確的順序調(diào)用析構(gòu)函數(shù)。如果虛構(gòu)函數(shù)不是虛的則指揮調(diào)用指針類型的析構(gòu)函數(shù),而不會(huì)調(diào)用指針指向的類型的析構(gòu)函數(shù),這樣會(huì)出現(xiàn)錯(cuò)誤。
- 在派生類中的虛函數(shù)調(diào)用基類的同名虛函數(shù)時(shí)需要使用基類類名域作用符,否則會(huì)出現(xiàn)無限循環(huán)調(diào)用。
- 派生類不能直接訪問基類的private成員和方法,必須通過protected或者public來進(jìn)行訪問。
- 構(gòu)造函數(shù)不能是虛函數(shù)。(沒有意義)
- 友元函數(shù)不能是虛函數(shù),因?yàn)橛言瘮?shù)不是類成員。
- 在類的虛函數(shù)聲明后面加
=0
即將此函數(shù)定義為純虛函數(shù),包括純虛函數(shù)的類為抽象基類(abstract base class ,ABC)。抽象基類不能創(chuàng)建該類的對象。由抽象基類派生出來的類成為具體類(concrete)。可以將ABC看成一種必須實(shí)施的接口。
- 當(dāng)基類 和派生類都采用動(dòng)態(tài)內(nèi)存分配時(shí),派生類的析構(gòu)函數(shù)、復(fù)制構(gòu)造函數(shù)、賦值運(yùn)算符函數(shù)都必須使用相應(yīng)基類方法來處理基本元素。對于析構(gòu)函數(shù)這是自動(dòng)完成的;對于構(gòu)造函數(shù),這是通過在初始化列表中調(diào)用街壘的復(fù)制構(gòu)造函數(shù)來完成的(如果不這樣做,將自動(dòng)調(diào)用 基類的默認(rèn)構(gòu)造函數(shù));對于賦值運(yùn)算符,這是通過使用作用域解析運(yùn)算符顯示調(diào)用基類的賦值運(yùn)算符來完成的。例如:
class baseDMA {
private:char * point;
...
}
baseDMA& baseDMA::operator= (const baseDMA& rs) {
if(this==&rs) return *this;
delete[] point;//釋放動(dòng)態(tài)分配的內(nèi)存
...//重新動(dòng)態(tài)分配內(nèi)存,復(fù)制內(nèi)容
return *this;
}
class hasDMA :public baseDMA{
private: char * point2;
...
}
hasDMA& hasDMA::operator= (const hasDMA& rs) {
if(this==&rs) return *this;
baseDMA::operator=(hs);//復(fù)制基類部分
/*通過使用函數(shù)方式顯示調(diào)用基類的賦值函數(shù)作用類似于
*this=rs;只不過如果不使用函數(shù)方式就沒法使用域作用符,
此時(shí)函數(shù)會(huì)默認(rèn)調(diào)用hasDMA::operator=(),從而形成無限遞歸調(diào)用*/
delete[] point2;
...//動(dòng)態(tài)分配內(nèi)存,復(fù)制內(nèi)容
return *this;
}
構(gòu)造由內(nèi)而外進(jìn)行,Container的構(gòu)造函數(shù)首先調(diào)用Component的default構(gòu)造函數(shù),然后才執(zhí)行自己。(即由編譯器默認(rèn)再初始化列表中調(diào)用Component的構(gòu)造函數(shù))
Container::Container(...):Component(){...}
析構(gòu)由外而內(nèi),Container的析構(gòu)函數(shù)先執(zhí)行自己,然后在調(diào)用Component的析構(gòu)函數(shù)(即由編譯器默認(rèn)在Container的析構(gòu)函數(shù)的最后調(diào)用Component的析構(gòu)函數(shù))
Container::~Container(...){... ~Component(); }
構(gòu)造由內(nèi)而外進(jìn)行,Derived的構(gòu)造函數(shù)首先調(diào)用Base的default構(gòu)造函數(shù),然后才執(zhí)行自己。(即由編譯器默認(rèn)再初始化列表中調(diào)用Base的構(gòu)造函數(shù))
Derived::Derived(...):Base(){...}
析構(gòu)由外而內(nèi),Container的析構(gòu)函數(shù)先執(zhí)行自己,然后在調(diào)用Base的析構(gòu)函數(shù)(即由編譯器默認(rèn)在Derived的析構(gòu)函數(shù)的最后調(diào)用Base的析構(gòu)函數(shù))
Derived::~Derived(...){... ~Base(); }
base class的dtor必須是virtual,否則會(huì)出現(xiàn)undefined behavior
繼承應(yīng)配合virtual函數(shù)來使用。
如果函數(shù)沒有使用關(guān)鍵字virtual修飾,則程序?qū)⒏鶕?jù)對象、引用類型或指針類型調(diào)用函數(shù)。如果使用virtual修飾函數(shù)則程序?qū)⒏鶕?jù)引用或者指針 指向的對象類型 進(jìn)行選擇方法。但是將函數(shù)定義成virtual會(huì)增加程序的空間和時(shí)間開銷。在基類方法的聲明中使用關(guān)鍵字virtual可是該方法在基類以及所有的派生類(包括從派生類派生出來的類)中是虛的。
=0
即將此函數(shù)定義為純虛函數(shù),包括純虛函數(shù)的類為抽象基類(abstract base class ,ABC)。抽象基類不能創(chuàng)建該類的對象。由抽象基類派生出來的類成為具體類(concrete)。可以將ABC看成一種必須實(shí)施的接口。class baseDMA {
private:char * point;
...
}
baseDMA& baseDMA::operator= (const baseDMA& rs) {
if(this==&rs) return *this;
delete[] point;//釋放動(dòng)態(tài)分配的內(nèi)存
...//重新動(dòng)態(tài)分配內(nèi)存,復(fù)制內(nèi)容
return *this;
}
class hasDMA :public baseDMA{
private: char * point2;
...
}
hasDMA& hasDMA::operator= (const hasDMA& rs) {
if(this==&rs) return *this;
baseDMA::operator=(hs);//復(fù)制基類部分
/*通過使用函數(shù)方式顯示調(diào)用基類的賦值函數(shù)作用類似于
*this=rs;只不過如果不使用函數(shù)方式就沒法使用域作用符,
此時(shí)函數(shù)會(huì)默認(rèn)調(diào)用hasDMA::operator=(),從而形成無限遞歸調(diào)用*/
delete[] point2;
...//動(dòng)態(tài)分配內(nèi)存,復(fù)制內(nèi)容
return *this;
}