(Boolan) C++面向對象編程(上) 第三周筆記

本周內容算是Part1的收尾了,通過這三周的課程會對面向對象編程這個概念有了更為深刻的理解,信息量有些大,可能還需要之后再復習。

  1. 首先是OOP里面對于class這個概念的延伸,主要講了三種class之間的關系,有的教材上將類與類之間的關系講的像人生哲學一樣,但是只要理解這三種關系就能繼續之后的系列課程。

對象之間的關系可以概括為繼承(Inheritance)、組合(Composition)和代理(Delegation)3種。

7086751-c535ae8da544ed30.png
  • Composition組合, 表示has-a, 一個class里面完整包含另一個class

Composition概念早就存在,在c語言的struct中,使用了別的struct或者string等,都是組合(c語言實現面向對象就是用了這個特性)。

舉例來說,queue中含有deque,即queue和deque是復合關系。(即只要A含有B,則就是一種復合關系)。但看代碼,queue中的功能,都由dequeue完成。Dequeu的功能比較強大,就比較特殊了,成為一種adapter模式。

185929-83fb1071c78c3838.png

composition的構造是由內而外的:B的構造函數會首先調用A的默認構造函數(編譯器自己調用,如果需要傳遞參數,需要在初始化列表顯示調用),然后在調用自己的構造函數

Conainter::Container():: Component() {…} //編譯器會自己去構造Component對象

container的構造函數首先調用component的default構造函數

composition的析構是由外而內的:B的析構函數首先執行自己的,然后才調用A的析構函數。Container的析構先調用自己,然后再調用Component的析構函數(編譯器幫助完成,我們只要管理好Container的構造和析構就可以)。

如果Component的構造函數有多個,則需要顯式的調用構造函數。

  • Delegation委托,Composition by reference

Tips:復合是兩者生命一起出現,委托(又稱Composition by reference)Container先創建起來,等到需要Component的時候,才創建Component,即不同步。

a.設計模式:Handle/Body(pointer to implementation:我有一個指針,去指向為我實現所有功能的那一個類。——指針可以指向不同的實現類,所以又稱編譯防火墻:(下圖)左邊的永遠不用再編譯,要編譯的只是(下圖)右邊的。

185929-83fb1071c78c3838.png

b.共享

如上圖紅圈所示,a,b,c三個指針指向同一個字符串,即共享一個字符串,這樣的好處是節省內存空間(當然,共享的內容必須完全一樣),但是需要注意,當想改變一個指針指向的內容時,其余兩個指針指向的值也就隨之改變,也就是牽一發而動全身。

  • Inheritance,類的繼承,是新的類從已有類那里得到已有的特性。或從已有類產生新類的過程就是類的派生。原有的類稱為基類或父類,產生的新類稱為派生類或子類。
    Inheritance的聲明:
    class 派生類名:繼承方式 基類名1, 繼承方式 基類名2,...,繼承方式 基類名n
{

subclass成員聲明;

};
  • 一個派生類可以同時有多個基類,這種情況稱為多重繼承,派生類只有一個基類,稱為單繼承。直接派生,間接派生。
  • 繼承方式規定了如何訪問基類繼承的成員。繼承方式有public, private, protected。如果不顯示給出繼承方式,默認為private繼承。繼承方式指定了派生類成員以及類外對象對于從基類繼承來的成員的訪問權限。
  • 派生類繼承基類中除構造和析構函數以外的所有成員。
  • 派生類生成:
    吸收基類成員(除構造析構函數以外的所有成員);
    改造基類成員(根據繼承方式調整基類成員的訪問,函數在子類中的覆蓋,以及虛函數在子類中的覆蓋)

Tips:C++類的3種繼承方式,分別是public繼承,protected繼承,private繼承。

最常用的還是public繼承。class默認的是private繼承,它的member如果沒寫權限也是默認.
3個繼承權限的區別:

class ex0

{

private:

void showPrivate(){cout<<"this is private function!";}

public:

void showPublic(){cout<<"this is public function!";}

protected:

void showProtected(){cout<<"this is protected function!";}

};

class ex1:public ex0

{

public:

void func()

{

showPrivate();

//錯誤因為此函數訪問權限只有基類 ex0 自己有

showPublic();

showProtected();

}

};

class ex2:protected ex0

{

public:

void func()

{

showPrivate();

//錯誤因為此函數訪問權限只有基類 ex0 自己有

showPublic();

//正確, 但是此函數由于 ex2 的保護繼承這個函數的訪問權限已經變成了 protected,

//也就是說對于外部類來說已經不具備訪問這個函數的權限了

showProtected();

}

};

class ex3:private ex0

{

public:

void func()

{

showPrivate();

//錯誤因為此函數訪問權限只有基類 ex0 自己有

showPublic();

//正確, 但是此函數由于 ex3 的私有繼承這個函數的訪問權限已經變成了 private,

//也就是說對于外部類和派生類來說已經不具備訪問這個函數的權限了

showProtected();

//正確, 但是此函數由于 ex3 的私有繼承這個函數的訪問權限已經變成了 private,

//也就是說對于外部類和派生類來說已經不具備訪問這個函數的權限了

}

};

  1. Inheritance(繼承)with virtual functions

繼承搭配著虛函數。

子類可以繼承父類的所有內容,包括數據和函數。從內存角度,可以繼承數據;對于函數,不能從內存角度理解,而是子類繼承了父類的函數調用權。

函數分為三種情況:

  • non virtual function:你不希望derived class重新定義override
  • virtual function:希望derived class的重新定義override。已有默認定義。
  • pure virtual:你希望derived class一定要重新定義。沒有默認定義。

虛函數(Virtual Function)是通過一張虛函數表(Virtual Table)來實現的。簡稱為V-Table。
在這個表中,主是要一個類的虛函數的地址表,這張表解決了繼承、覆蓋的問題,保證其真實反應實際的函數。這樣,在有虛函數的類的實例中這個表被分配在了 這個實例的內存中,所以,當我們用父類的指針來操作一個子類的時候,這張虛函數表就顯得由為重要了,它就像一個地圖一樣,指明了實際所應該調用的函數。
編譯器必需要保證虛函數表的指針存在于對象實例中最前面的位置(這是為了保證正確取到虛函數的偏移量)。 這意味著我們通過對象實例的地址得到這張虛函數表,然后就可以遍歷其中函數指針,并調用相應的函數。

假設有下面這個類:

class Base {
public:
    virtual void f( ) { cout << "Base::f" << endl; }
    virtual void g( ) { cout << "Base::g" << endl; }
    virtual void h( ) { cout << "Base::h" << endl; }
};

我們可以通過Base的實例來得到虛函數表。

    Base b;
    cout << "虛函數表地址:" << (int*)(&b) << endl;
    cout << "虛函數表 — 第一個函數地址:" << (int*)*(int*)(&b) << endl;

可得到:

虛函數表地址:0012FED4
虛函數表 — 第一個函數地址:0044F148
  1. 設計模式:Prototype(原型模式)
    用原型實例制定創建對象的種類,并且通過拷貝創建新的對象;

類圖:

5665430-1f227b1e63bb9b76.jpg

核心是克隆函數的運用
組成元素:
Prototype:聲明克隆自身的接口;
ConcretePrototype:實現克隆自身的操作;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容