C++面向對象高級編程 第三周 博覽網(wǎng)

面向對象編程

Inheritance繼承 Composition復合 Delegation委托

Composition(復合) 表示 has a

  • Container -> Component
    構造由內而外進行,Container的構造函數(shù)首先調用Component的default構造函數(shù),然后才執(zhí)行自己。(即由編譯器默認再初始化列表中調用Component的構造函數(shù))
    Container::Container(...):Component(){...}
    析構由外而內,Container的析構函數(shù)先執(zhí)行自己,然后在調用Component的析構函數(shù)(即由編譯器默認在Container的析構函數(shù)的最后調用Component的析構函數(shù))
    Container::~Container(...){... ~Component(); }

Delegation(委托).Composition by reference.Handle/Body模式(編譯防火墻模式)

  • 在類內有一個指向具體實現(xiàn)類的指針,類只提供一個調用的接口而不負責具體實現(xiàn),這樣可以通過讓指針指向不同的具體實現(xiàn)類來改變具體實現(xiàn)而不用影響客戶端,也不用全部重新編譯。

Inheritance(繼承),表示Is a

  • Derived -> Base
    構造由內而外進行,Derived的構造函數(shù)首先調用Base的default構造函數(shù),然后才執(zhí)行自己。(即由編譯器默認再初始化列表中調用Base的構造函數(shù))
    Derived::Derived(...):Base(){...}
    析構由外而內,Container的析構函數(shù)先執(zhí)行自己,然后在調用Base的析構函數(shù)(即由編譯器默認在Derived的析構函數(shù)的最后調用Base的析構函數(shù))
    Derived::~Derived(...){... ~Base(); }
    base class的dtor必須是virtual,否則會出現(xiàn)undefined behavior
    繼承應配合virtual函數(shù)來使用。
    如果函數(shù)沒有使用關鍵字virtual修飾,則程序將根據(jù)對象、引用類型或指針類型調用函數(shù)。如果使用virtual修飾函數(shù)則程序將根據(jù)引用或者指針 指向的對象類型 進行選擇方法。但是將函數(shù)定義成virtual會增加程序的空間和時間開銷。在基類方法的聲明中使用關鍵字virtual可是該方法在基類以及所有的派生類(包括從派生類派生出來的類)中是虛的。
  • 為基類聲明一個虛析構函數(shù)是一種慣例(除非它不做基類),這樣可以確保釋放派生對象時按正確的順序調用析構函數(shù)。如果虛構函數(shù)不是虛的則指揮調用指針類型的析構函數(shù),而不會調用指針指向的類型的析構函數(shù),這樣會出現(xiàn)錯誤。
  • 在派生類中的虛函數(shù)調用基類的同名虛函數(shù)時需要使用基類類名域作用符,否則會出現(xiàn)無限循環(huán)調用。
  • 派生類不能直接訪問基類的private成員和方法,必須通過protected或者public來進行訪問。
  • 構造函數(shù)不能是虛函數(shù)。(沒有意義)
  • 友元函數(shù)不能是虛函數(shù),因為友元函數(shù)不是類成員。
  • 在類的虛函數(shù)聲明后面加=0即將此函數(shù)定義為純虛函數(shù),包括純虛函數(shù)的類為抽象基類(abstract base class ,ABC)。抽象基類不能創(chuàng)建該類的對象。由抽象基類派生出來的類成為具體類(concrete)??梢詫BC看成一種必須實施的接口。
  • 當基類 和派生類都采用動態(tài)內存分配時,派生類的析構函數(shù)、復制構造函數(shù)、賦值運算符函數(shù)都必須使用相應基類方法來處理基本元素。對于析構函數(shù)這是自動完成的;對于構造函數(shù),這是通過在初始化列表中調用街壘的復制構造函數(shù)來完成的(如果不這樣做,將自動調用 基類的默認構造函數(shù));對于賦值運算符,這是通過使用作用域解析運算符顯示調用基類的賦值運算符來完成的。例如:
class baseDMA { 
    private:char * point;
    ...
}
baseDMA& baseDMA::operator= (const baseDMA& rs) {
    if(this==&rs) return *this;
    delete[] point;//釋放動態(tài)分配的內存
    ...//重新動態(tài)分配內存,復制內容
    return *this;
}
class hasDMA :public baseDMA{
    private: char * point2;
    ...
}
hasDMA& hasDMA::operator= (const hasDMA& rs) {
    if(this==&rs) return *this;
    baseDMA::operator=(hs);//復制基類部分
    /*通過使用函數(shù)方式顯示調用基類的賦值函數(shù)作用類似于
    *this=rs;只不過如果不使用函數(shù)方式就沒法使用域作用符,
    此時函數(shù)會默認調用hasDMA::operator=(),從而形成無限遞歸調用*/
    delete[] point2;
    ...//動態(tài)分配內存,復制內容
    return *this;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容