最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

C++ Primer 筆記-第15章 面向?qū)ο蟪绦蛟O(shè)計(jì)

2023-02-21 21:06 作者:Code有毒  | 我要投稿

15.1 OOP:概述

  1. 面向?qū)ο蟪绦蛟O(shè)計(jì)(object-oriented programming)的核心思想是:數(shù)據(jù)抽象、繼承動(dòng)態(tài)綁定

  2. 數(shù)據(jù)抽象:可以將類的接口與實(shí)現(xiàn)分離。

  3. 繼承(inheritance):可以定義相似的類型并對(duì)其相似關(guān)系建模。

  4. 動(dòng)態(tài)綁定(dynamic binding):可以在一定程度上忽略相似類型的區(qū)別,而以統(tǒng)一的方式使用它們的對(duì)象。

  5. 動(dòng)態(tài)綁定有時(shí)又被稱為運(yùn)行時(shí)綁定(run-time binding)

  6. 在C++中,當(dāng)使用基類的引用(或指針)調(diào)用一個(gè)虛函數(shù)時(shí)將發(fā)生動(dòng)態(tài)綁定。

15.2 定義基類和派生類

15.2.1 定義基類

  1. 基類通常都應(yīng)該定義一個(gè)虛析構(gòu)函數(shù),即使該函數(shù)不執(zhí)行任何實(shí)際操作也是如此。

  2. c++中,基類必須將它的兩種成員函數(shù)區(qū)分開:一種是基類希望其派生類進(jìn)行覆蓋的函數(shù)(虛函數(shù))。一種是基類希望派生類直接繼承而不要改變的函數(shù)。

  3. 成員函數(shù)如果沒被聲明為虛函數(shù),則其解析過程發(fā)生在編譯時(shí)而非運(yùn)行時(shí)。

15.2.2 定義派生類

  1. 訪問說明符(public、protected和private)的作用是:控制派生類從基類繼承而來的成員是否對(duì)派生類的用戶可見。

  2. 如果派生類沒有覆蓋其基類中的某個(gè)虛函數(shù),則該虛函數(shù)的行為類似于其他的普通成員,派生類會(huì)直接繼承其在基類中的版本。

  3. c++標(biāo)準(zhǔn)并沒有明確規(guī)定派生類的對(duì)象在內(nèi)存中如何分布。一個(gè)對(duì)象中,繼承自基類的部分和派生類自定義的部分在內(nèi)存中不一定是連續(xù)存儲(chǔ)的。

  4. 盡管在派生類對(duì)象中含有從基類繼承而來的成員,但是派生類并不能直接初始化這些成員。和其他創(chuàng)建了基類對(duì)象的代碼一樣,派生類也必須使用基類的構(gòu)造函數(shù)來初始化它的基類部分。

  5. 如果基類定義了一個(gè)靜態(tài)成員,則在整個(gè)繼承體系中只存在該成員的唯一定義。不論從基類中派生出多少個(gè)派生類,對(duì)于每個(gè)靜態(tài)成員來說都只存在唯一的實(shí)例。

  6. 如果我們想將某個(gè)類用作基類,則該類必須已經(jīng)定義而非僅僅聲明。

  7. 一個(gè)類不能派生它本身。

  8. 最終的派生類將包含它的直接基類的子對(duì)象以及每個(gè)間接基類的子對(duì)象。

  9. c++11新標(biāo)準(zhǔn)提供了一種防止繼承發(fā)生的方法,即在類名后跟一個(gè)關(guān)鍵字?final

15.2.3 類型轉(zhuǎn)換與繼承

  1. 我們可以將基類的指針或引用綁定到派生類對(duì)象上。當(dāng)使用基類的引用(或指針)時(shí),實(shí)際上我們不清楚該引用(或指針)所綁定對(duì)象的真實(shí)類型。

  2. 智能指針類也支持派生類向基類的類型轉(zhuǎn)換,可以將一個(gè)派生類對(duì)象的指針存儲(chǔ)在一個(gè)基類的智能指針內(nèi)。

  3. 當(dāng)使用存在繼承關(guān)系的類型時(shí),必須將一個(gè)變量或其他表達(dá)式的**靜態(tài)類型(static type)與該表達(dá)式表示對(duì)象的動(dòng)態(tài)類型(dynamic type)**區(qū)分開來:
    (1) 表達(dá)式的靜態(tài)類型在編譯時(shí)總是已知的,它是變量聲明時(shí)的類型或表達(dá)式生成的類型。
    (2) 動(dòng)態(tài)類型則是變量或表達(dá)式表示的內(nèi)存中的對(duì)象的類型。動(dòng)態(tài)類型直到運(yùn)行時(shí)才可知。
    (3) 如果表達(dá)式既不是引用也不是指針,則它的動(dòng)態(tài)類型永遠(yuǎn)與靜態(tài)類型一致。

  4. 不存在從基類向派生類的隱式類型轉(zhuǎn)換。

class Quote {...}

class Bulk_quote : public Quote {...}

Quote base; ? ? ? ? ? ? ? ? ?????????????// 基類對(duì)象

Bulk_quote derived; ? ? ? ? ?????????// 派生類對(duì)象

Quote* baseP1 = &derived; ? ???// 正確:基類指針綁派生類對(duì)象

Quote& baseRef = derived;? ? ??// 正確:基類引用綁派生類對(duì)象

Bulk_quote* bulkP1 = &base;???// 錯(cuò)誤:不能派生類指針綁基類對(duì)象

Bulk_quote& bulkRef = base;???// 錯(cuò)誤:不能派生類引用綁基類對(duì)象

Quote* baseP2 = &derived;? ?? ?// 正確:基類指針綁派生類對(duì)象

Bulk_quote* bulkP2 = baseP2; // 錯(cuò)誤:不能將基類轉(zhuǎn)換成派生類

  1. 編譯器在編譯時(shí)無法確定某個(gè)特定的轉(zhuǎn)換在運(yùn)行時(shí)是否安全,因?yàn)榫幾g器只能通過檢查指針或引用的靜態(tài)類型來推斷該轉(zhuǎn)換是否合法。但我們可以使用顯式的方式進(jìn)行類型轉(zhuǎn)換:

  2. (1) 如果在基類中含有一個(gè)或多個(gè)虛函數(shù),我們可以使用?dynamic_cast?請(qǐng)求一個(gè)類型轉(zhuǎn)換,該轉(zhuǎn)換的安全檢查將在運(yùn)行時(shí)執(zhí)行。
    (2)如果我們已知某個(gè)基類向派生類的轉(zhuǎn)換是安全的,則可以使用?static_cast?來強(qiáng)制覆蓋掉編譯器的檢查工作。

  3. 當(dāng)我們用一個(gè)派生類對(duì)象為一個(gè)基類對(duì)象初始化或賦值時(shí),只有該派生類對(duì)象中的基類部分會(huì)被拷貝、移動(dòng)或賦值,它的派生類部分將被忽略掉。

Bulk_quote bulk; ? ?// 派生類對(duì)象

Quote item(bulk); ? // 使用Quote::Quote(const Quote&)構(gòu)造函數(shù)

item = bulk;? ? ? ? ? ??// 調(diào)用Quote::operator=(const Quote&)


15.3 虛函數(shù)

  1. OOP的核心思想是多態(tài)性(polymorphism)。引用或指針的靜態(tài)類型與動(dòng)態(tài)類型不同這一事實(shí)正是c++支持多態(tài)性的根本所在。

  2. 當(dāng)且僅當(dāng)對(duì)通過指針或引用調(diào)用虛函數(shù)時(shí),才會(huì)在運(yùn)行時(shí)解析該調(diào)用,也只有在這種情況下對(duì)象的動(dòng)態(tài)類型才有可能與靜態(tài)類型不同。

  3. 基類中的虛函數(shù)在派生類中隱含地也是一個(gè)虛函數(shù)。當(dāng)派生類覆蓋了某個(gè)虛函數(shù)時(shí),該虛函數(shù)在基類中的形參必須與派生類中的形參嚴(yán)格匹配。返回值也是如此。

  4. 上述規(guī)定有個(gè)例外:當(dāng)類的虛函數(shù)返回類型是類本身的指針或引用時(shí),上述規(guī)則無效。也就是說,如果D由B派生得到,則基類的虛函數(shù)可以返回B而派生類的對(duì)于函數(shù)可以返回D,只不過這樣的返回類型要求從D到B的類型轉(zhuǎn)換是可訪問的。

  5. 派生類如果定義了一個(gè)函數(shù)與基類中虛函數(shù)的名字相同但是形參列表不同,這是合法的。這時(shí)派生類的函數(shù)并不會(huì)覆蓋調(diào)基類中的版本。但是就實(shí)際編程習(xí)慣來說這樣做往往意味著該情況是不小心將虛函數(shù)的形參列表搞錯(cuò)了。

  6. 我們可以使用?override?關(guān)鍵字標(biāo)記了某個(gè)虛函數(shù)。但該函數(shù)并沒有覆蓋已存在的虛函數(shù),此時(shí)編譯器將會(huì)報(bào)錯(cuò)。

  7. 我們還能把某個(gè)函數(shù)指定為?final,之后任何嘗試覆蓋該函數(shù)的操作將引發(fā)錯(cuò)誤。

struct B {

? ?virtual void f1(int) const;

? ?virtual void f2();

? ?void f3();

? ?virtual f4() final;

}

struct D1 : public B {

? ?void f1(int) const override; // 正確:f1與基類中的f1匹配

? ?void f2(int) override; ? ? ? // 錯(cuò)誤:B沒有形如f2(int)的函數(shù)

? ?void f3() override; ? ? ? ? ?// 錯(cuò)誤:f3不是虛函數(shù)

? ?void f4() override; ? ? ? ? ?// 錯(cuò)誤:f4已經(jīng)被聲明成final

? ?void f5() override; ? ? ? ? ?// 錯(cuò)誤:B沒有名為f5的函數(shù)

}

  1. 如果虛函數(shù)使用默認(rèn)實(shí)參,則基類和派生類中定義的默認(rèn)實(shí)參最好一致。如不一致,無論是基類還是派生類調(diào)用該虛函數(shù),都只會(huì)使用基類的默認(rèn)實(shí)參。

  2. 使用作用域運(yùn)算符可以實(shí)現(xiàn)對(duì)虛函數(shù)的調(diào)用不進(jìn)行動(dòng)態(tài)綁定,而是強(qiáng)迫其執(zhí)行虛函數(shù)的某個(gè)特定版本。

double undiscouted = baseP->Quote::net_price(42);

  1. 通常情況下,只有成員函數(shù)(或友元)中的代碼才需要使用作用域運(yùn)算符來回避虛函數(shù)機(jī)制。

  2. 如果一個(gè)派生類虛函數(shù)需要調(diào)用它的基類版本,但是沒有使用作用域運(yùn)算符,則在運(yùn)行時(shí)該調(diào)用將被解析為對(duì)派生類版本自身的調(diào)用,從而導(dǎo)致無限遞歸。

15.4 抽象基類

  1. 通過在函數(shù)體的位置(即在聲明語句的分號(hào)之前)書寫?=0?就可以將這個(gè)虛函數(shù)說明為純虛函數(shù)(pure virtual function),這樣就清晰的告訴用戶當(dāng)前這個(gè)虛函數(shù)沒有實(shí)際的意義。

  2. 我們無須為純虛函數(shù)提供實(shí)現(xiàn)。當(dāng)然我們也能為純虛函數(shù)提供實(shí)現(xiàn),不過函數(shù)體必須定義在類的外部。

  3. 含有(或者未覆蓋直接繼承)純虛函數(shù)的類是抽象基類(abstract base class)。抽象基類負(fù)責(zé)定義接口,而后續(xù)的其他類可以覆蓋該接口。我們不能(直接)創(chuàng)建一個(gè)抽象基類的對(duì)象。

15.5 訪問控制與繼承

  1. 一個(gè)類使用?protected?關(guān)鍵字來聲明那些它希望與派生類分享但是不想被其他公共訪問使用的成員。
    (1) 和私有成員類似,受保護(hù)的成員對(duì)于類的用戶來說是不可訪問的。
    (2) 和公有成員類似,受保護(hù)的成員對(duì)派生類的成員和友元來說是可訪問的。
    (3) 派生類的成員或友元只能通過派生類對(duì)象來訪問基類的受保護(hù)成員。派生類對(duì)于一個(gè)基類對(duì)象中的受保護(hù)成員沒有任何訪問特權(quán)。

class Base {

protected: ? ?int prot_men; ? // 受保護(hù)的成員

};

class Sneaky : public Base {

? ?friend void clobber(Sneaky&); ? // 能訪問Sneaky::prot_mem

? ?friend void clobber(Base&); ? ? // 不能訪問Base::prot_mem

? ?int j; ? ? ? ? ? ? ? ? ? ? ? ? ?// j默認(rèn)是private

};// 正確:clobber能訪問Sneaky對(duì)象的private和protected成員

void clobber(Sneaky& s) { s.j = s.prot_mem = 0; }

// 錯(cuò)誤:Clobber不能訪問Base的Protected成員

void clobber(Base& b) { b.prot_mem = 0; }

  1. 某個(gè)類對(duì)其繼承而來的成員的訪問權(quán)限受到兩個(gè)因素的影響:

    (1) 在基類中該成員的訪問說明符。

    (2) 在派生類的派生列表中的訪問說明符。

  2. 其中?派生訪問說明符?對(duì)?派生類的成員(及友元)?能否訪問其直接基類的成員沒有什么影響。對(duì)基類成員的訪問權(quán)限只與基類中的訪問說明符有關(guān)。

class Base {

public: ? ?void pub_mem();

protected: ? ?int prot_men;

private: ? ?char priv_mem;

};

struct Pub_Derv : public Base {

? ?// 正確:派生類能訪問public成員

? ?void e() { pub_mem(); }

? ?// 正確:派生類能訪問protected成員

? ?int f() { return prot_mem; }

? ?// 錯(cuò)誤:private 成員對(duì)于派生類來說是不可訪問的

? ?char g() { return priv_mem; }

};

struct Prot_Der : protected Base {

? ?// proteced 不影響派生類的訪問權(quán)限

? ?// 同上... ...

};

struct Priv_Der : private Base {

? ?// private 不影響派生類的訪問權(quán)限 ? ?

// 同上... ...

};

  1. 派生訪問說明符的目的是控制派生類用戶(包括派生類的派生類在內(nèi))?對(duì)于基類成員的訪問權(quán)限:

// 派生訪問說明符 控制 派生類用戶 的訪問權(quán)限:

Pub_Derv d1; ? ?// 繼承自Base的成員是public的

Prot_Derv d2; ? // 繼承自Base的成員是protected的

Priv_Derv d3; ? // 繼承自Base的成員是private的

d1.pub_mem(); ? // 正確:pub_mem在派生類中是public的

d2.pub_mem(); ? // 錯(cuò)誤:pub_mem在派生類中是protected的

d3.pub_mem(); ? // 錯(cuò)誤:pub_mem在派生類中是private的

// 派生訪問說明符 控制 派生類的派生類 的訪問權(quán)限:

struct Derived_from_Public : public Pub_Derv {

? ?// 正確:Base::Prot_mem在Pub_Derv中仍然是protected的

? ?int use_base() { return prot_mem; }

}

struct Derived_from_Protected : public Prot_Derv {

? ?// 正確:Base::Prot_mem在Prot_Derv中仍然是protected的

? ?int use_base() { return prot_mem; }

}

struct Derived_from_Private : public Priv_Derv {

? ?// 錯(cuò)誤:Base::prot_mem在Priv_Derv中是Private的

? ?int use_base() { return prot_mem; }

};

  1. 派生訪問說明符 對(duì)?派生類用戶?的影響總結(jié):

    (1)?public繼承時(shí),基類的成員的權(quán)限不受影響。
    (2)?protected繼承時(shí),基類的public成員會(huì)轉(zhuǎn)為protected成員,其余的權(quán)限不變。
    (3)?private繼承時(shí),基類的publicprotected成員均會(huì)轉(zhuǎn)為private成員,也就是說所有成員都成private的了。

  2. 對(duì)于代碼中的某個(gè)給定節(jié)點(diǎn)來說,基類的公有成員是可訪問的,則派生類向基類的類型轉(zhuǎn)換也是可訪問的,反之則不行。

  3. 有三種用戶:
    (1) 普通用戶:普通用戶編寫的代碼使用類的對(duì)象,這部分代碼只能訪問類的公有(接口)成員;
    (2) 類的實(shí)現(xiàn)者:負(fù)責(zé)編寫類的成員和友元的代碼,成員和友元既能訪問類的公有部分,也能訪問類的私有(實(shí)現(xiàn))部分。
    (3) 派生類:基類把它希望派生類能夠使用的部分聲明成受保護(hù)的。普通用戶不能訪問受保護(hù)的成員,而派生類及其友元仍舊不能訪問私有成員。

  4. 和其他類一樣,基類應(yīng)該將其接口成員聲明為公有的,同時(shí)將屬于其實(shí)現(xiàn)細(xì)節(jié)的函數(shù)部分分成兩組:
    (1) 一組可供派生類訪問,應(yīng)該聲明為受保護(hù)的,這樣派生類就能在實(shí)現(xiàn)自己的功能時(shí)使用基類的這些操作和數(shù)據(jù);
    (2) 另一組只能由基類及基類的友元訪問,應(yīng)該聲明為私有的。

  5. 友元關(guān)系不能傳遞,同樣友元關(guān)系也不能繼承。

  6. 每個(gè)類負(fù)責(zé)控制各自成員的訪問權(quán)限(*基類的訪問權(quán)限由基類本身控制,也就是說即使對(duì)于派生類的基類成員的權(quán)限,也不由派生類控制而由基類控制)。

  7. 通過在類的內(nèi)部使用?using?聲明語句,可以將該類的直接或間接基類種的任何可訪問成員(非私有成員)?標(biāo)記出來。using?聲明語句中名字的訪問權(quán)限由該?using?聲明語句之前的訪問說明符來決定:

class Base {

public: ? ?std::size_t size() const { return n; }

protected: ? ?std::size_t n;

private: ? ?int i;

}

// 注意是private繼承

class Derived : Private Base {

// 正確

public:

? ?using Base::size;

protected:

? ?using Base::n;

// 錯(cuò)誤:只能為非私有成員提供聲明

public:

? ?using Base::i;

protected:

? ?using Base::i;

}

  1. 使用?class?關(guān)鍵字定義的派生類是私有繼承的,使用?struct?關(guān)鍵字定義的派生類是公有繼承的。

  2. class?關(guān)鍵字和?struct?關(guān)鍵字唯一的差別就是默認(rèn)成員訪問說明符及默認(rèn)派生訪問說明符。除此之外再無其他不同之處。

class Base {};

struct D1 : Base {}; ? ?// 默認(rèn)public繼承

class D2 : Base {}; ? ? // 默認(rèn)private繼承

15.6 繼承中的類作用域

  1. 每個(gè)類定義自己的作用域,在這個(gè)作用域內(nèi)我們定義類的成員。

  2. 當(dāng)存在繼承時(shí),派生類的作用域嵌套在其基類的作用域之內(nèi)。

  3. 如果一個(gè)名字在派生類的作用域內(nèi)無法正確解析,則編譯器將繼續(xù)在外層的基類作用域中尋找該名字的定義。

  4. 一個(gè)對(duì)象、引用或指針的靜態(tài)類型決定了該對(duì)象的哪些成員是可見的。即使靜態(tài)類型與動(dòng)態(tài)類型可能不一致(當(dāng)使用基類的因引用或指針時(shí)會(huì)發(fā)生這種情況),但是我們能使用哪些成員仍然是由靜態(tài)類型決定的。

  5. 派生類的成員將隱藏同名的基類成員。

  6. 可以通過作用域運(yùn)算符來使用一個(gè)被隱藏的基類成員。

  7. 除了覆蓋繼承而來的虛函數(shù)之外,派生類最好不要重用其他定義在基類中的名字。

  8. 聲明在內(nèi)層作用域的函數(shù)并不會(huì)重載聲明在外層作用域的函數(shù),因此,定義在派生類中的函數(shù)不會(huì)重載其基類中的成員。

  9. 如果派生類(既內(nèi)層作用域)的成員與基類(既外層作用域)的某個(gè)成員同名,則派生類將在其作用域內(nèi)隱藏該基類成員。即使派生類成員和基類成員的形參列表不一致,基類成員也仍然會(huì)被隱藏掉。

  10. 成員函數(shù)無論是否是虛函數(shù)都可以被重載,如果派生類希望所有的重載版本對(duì)于它來說都是可見的,那么它需要覆蓋所有的版本,或者一個(gè)也不覆蓋。當(dāng)為重載的成員提供一條using聲明語句就無須覆蓋基類中的每一個(gè)重載版本了,此時(shí)派生類只需要定義其特有的函數(shù)就可以了,而無須為繼承而來的其他函數(shù)重新定義。

15.7 構(gòu)造函數(shù)與拷貝控制

15.7.1 虛析構(gòu)函數(shù)

  1. 繼承關(guān)系對(duì)基類拷貝控制最直接的影響是基類通常應(yīng)該定義一個(gè)虛析構(gòu)函數(shù),這樣就能動(dòng)態(tài)分配繼承體系中的對(duì)象了。如果基類的析構(gòu)函數(shù)不是虛函數(shù),則delete一個(gè)指向派生類對(duì)象的基類指針將產(chǎn)生未定義的行為。

  2. 虛析構(gòu)函數(shù)將阻止合成移動(dòng)操作。

15.7.2 合成拷貝控制與繼承

  1. 基類或派生類的合成拷貝控制成員的行為與其它合成的構(gòu)造函數(shù)、賦值運(yùn)算符或析構(gòu)函數(shù)類似:它們對(duì)類本身的成員依次進(jìn)行初始化、賦值或銷毀的操作。此外,這些合成的成員還負(fù)責(zé)使用直接基類中對(duì)應(yīng)的操作對(duì)一個(gè)對(duì)象的直接基類部分進(jìn)行初始化、賦值或銷毀的操作。

15.7.3 派生類的拷貝控制成員

  1. 當(dāng)派生類定義了拷貝或移動(dòng)操作時(shí),該操作負(fù)責(zé)拷貝或移動(dòng)包括基類部分成員在內(nèi)的整個(gè)對(duì)象。

  2. 默認(rèn)情況下,基類默認(rèn)構(gòu)造函數(shù)初始化派生類對(duì)象的基類部分。如果我們想拷貝(或移動(dòng))基類部分,則必須在派生類的構(gòu)造函數(shù)初始值列表中顯式地使用基類的拷貝(或移動(dòng))構(gòu)造函數(shù)。

  3. 派生類的賦值運(yùn)算符也必須顯式地為其基類部分賦值。

  4. 在析構(gòu)函數(shù)執(zhí)行完成后,對(duì)象的成員會(huì)被隱式銷毀。類似的,對(duì)象的基類部分也是隱式銷毀的。因此派生類析構(gòu)函數(shù)只負(fù)責(zé)銷毀由派生類自己分配的資源。

  5. 對(duì)象銷毀的順序正好與創(chuàng)建的順序相反:派生類析構(gòu)函數(shù)首先執(zhí)行,然后是基類的析構(gòu)函數(shù),以此類推,沿著繼承體系的反方向直至最后。

  6. 如果構(gòu)造函數(shù)或析構(gòu)函數(shù)調(diào)用了某個(gè)虛函數(shù),則我們應(yīng)該執(zhí)行與構(gòu)造函數(shù)或析構(gòu)函數(shù)所屬類型相對(duì)應(yīng)的虛函數(shù)版本。

15.7.4 繼承的構(gòu)造函數(shù)

  1. 在c++11新標(biāo)準(zhǔn)中,派生類能夠重用其直接基類定義的構(gòu)造函數(shù)。

  2. 通常情況下using聲明語句只是令某個(gè)名字在當(dāng)前作用域內(nèi)可見。而當(dāng)用作構(gòu)造函數(shù)時(shí),using聲明語句將令編譯器產(chǎn)生代碼。

class Bulk_quote : public Disc_quote {

public:

? ?using Disc_quote::Disc_quote; ? // 繼承Disc_quote的構(gòu)造函數(shù)

}

// 編譯器生成的構(gòu)造函數(shù)等價(jià)于:

Bulk_quote(const std::string& book, double price,

? ? ? ? ? ?std::size_t qty, double disc):

? ?Disc_quote(book, price, qty, disc) {}

  1. 一個(gè)構(gòu)造函數(shù)的?using?聲明不會(huì)改變?cè)摌?gòu)造函數(shù)的訪問級(jí)別。

  2. 一個(gè)構(gòu)造函數(shù)的?using?聲明不能指定?explicit?或?constexpr

  3. 當(dāng)一個(gè)基類構(gòu)造函數(shù)含有默認(rèn)實(shí)參時(shí),這些實(shí)參并不會(huì)被繼承。相反,派生類將獲得多個(gè)繼承的構(gòu)造函數(shù),其中每個(gè)構(gòu)造函數(shù)分別省略掉一個(gè)含有默認(rèn)實(shí)參的形參。

  4. 如果基類含有幾個(gè)構(gòu)造函數(shù),則除了兩個(gè)例外情況,大多數(shù)時(shí)候派生類會(huì)繼承所有這些構(gòu)造函數(shù)。
    (1) 第一個(gè)例外是派生類可以繼承一部分構(gòu)造函數(shù),而為其他構(gòu)造函數(shù)定義自己的版本。
    (2) 第二個(gè)例外是默認(rèn)、拷貝和移動(dòng)構(gòu)造函數(shù)不會(huì)被繼承。這些構(gòu)造函數(shù)按照正常規(guī)則被合成。

15.8 容器與繼承

  1. 當(dāng)我們使用容器存放繼承體系中的對(duì)象時(shí),通常必須采取間接存儲(chǔ)的方式。因?yàn)椴辉试S在容器中保存不同類型的元素,所以我們不能把具有繼承關(guān)系的多種類型的對(duì)象直接存放在容器當(dāng)中。

  2. 當(dāng)派生類對(duì)像被賦值給基類對(duì)象時(shí),其中的派生類部分將被“切掉”,因此容器和存在繼承關(guān)系的類型無法兼容。

  3. 當(dāng)我們希望在容器中存放具有繼承關(guān)系的對(duì)象時(shí),我們實(shí)際上存放的通常是基類的指針(更好的選擇是智能指針),這些指針?biāo)傅膶?duì)象的動(dòng)態(tài)類型可能是基類類型,也可能是派生類類型。

15.9 文本查詢程序再探

  1. 用面向?qū)ο蟮乃枷雭韺戇@個(gè)文本查詢程序。


C++ Primer 筆記-第15章 面向?qū)ο蟪绦蛟O(shè)計(jì)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
兴安县| 建湖县| 岱山县| 城固县| 宿州市| 瓮安县| 永定县| 库尔勒市| 大埔县| 敦化市| 卓资县| 图片| 榕江县| 柘城县| 中牟县| 措勤县| 泰兴市| 沙湾县| 中方县| 宁安市| 库车县| 博客| 鲁山县| 襄垣县| 绥化市| 榆中县| 亚东县| 巴中市| 岑溪市| 通江县| 高要市| 红桥区| 新营市| 永安市| 汉中市| 崇左市| 曲阜市| 祁连县| 长岭县| 南康市| 昆明市|