亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

深入解析C++編程中基類(lèi)與基類(lèi)的繼承的相關(guān)知識(shí)

 更新時(shí)間:2016年01月22日 15:29:57   投稿:goldensun  
這篇文章主要介紹了C++編程中基類(lèi)與基類(lèi)的繼承的相關(guān)知識(shí),包括多個(gè)基類(lèi)繼承與虛擬基類(lèi)等重要知識(shí),需要的朋友可以參考下

基類(lèi)
繼承過(guò)程將創(chuàng)建一個(gè)新的派生類(lèi),它由基類(lèi)的成員加上派生類(lèi)添加的任何新成員組成。在多重繼承中,可以構(gòu)建一個(gè)繼承關(guān)系圖,其中相同的基類(lèi)是多個(gè)派生類(lèi)的一部分。下圖顯示了此類(lèi)關(guān)系圖。

2016122151644636.jpeg (489×200)

單個(gè)基類(lèi)的多個(gè)實(shí)例
在該圖中,顯示了 CollectibleString 和 CollectibleSortable 的組件的圖形化表示形式。但是,基類(lèi) Collectible 位于通過(guò) CollectibleSortableString 路徑和 CollectibleString 路徑的 CollectibleSortable 中。若要消除此冗余,可以在繼承此類(lèi)類(lèi)時(shí)將其聲明為虛擬基類(lèi)。

多個(gè)基類(lèi)
如多重繼承中所述,類(lèi)可以從多個(gè)基類(lèi)派生。在多重繼承模型中(其中,類(lèi)派生自多個(gè)基類(lèi)),使用 base-list 語(yǔ)法元素指定基類(lèi)(請(qǐng)參閱概述中的“語(yǔ)法”一節(jié))。例如,可以指定派生自 CollectionOfBook 和 Collection 的 Book 的類(lèi)聲明:

// deriv_MultipleBaseClasses.cpp
// compile with: /LD
class Collection {
};
class Book {};
class CollectionOfBook : public Book, public Collection {
 // New members
};

指定基類(lèi)的順序并不重要,只不過(guò)在某些情況下,將調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)。在這些情況下,指定基類(lèi)的順序?qū)⒂绊懀?br /> 構(gòu)造函數(shù)進(jìn)行初始化的順序。如果您的代碼依賴(lài)要在 Book 部分之前初始化的 CollectionOfBook 的 Collection 部分,則規(guī)范的順序很重要。按照 base-list 中指定類(lèi)的順序執(zhí)行初始化。
調(diào)用析構(gòu)函數(shù)以進(jìn)行清理的順序。同樣,如果在銷(xiāo)毀另一部分時(shí)必須呈現(xiàn)類(lèi)的特定“部分”,則順序非常重要。按照與 base-list 中指定類(lèi)的順序相反的順序調(diào)用析構(gòu)函數(shù)。
注意
基類(lèi)的規(guī)范順序會(huì)影響類(lèi)的內(nèi)存布局。不要基于內(nèi)存中基成員的順序做出任何編程決策。
當(dāng)指定 base-list 時(shí),不能多次指定同一類(lèi)名。但是,可以將類(lèi)多次作為派生類(lèi)的間接基。

虛擬基類(lèi)
由于一個(gè)類(lèi)可能多次成為派生類(lèi)的間接基類(lèi),因此 C++ 提供了一種優(yōu)化這種基類(lèi)的工作方式的方法。虛擬基類(lèi)提供了一種節(jié)省空間和避免使用多重繼承的類(lèi)層次結(jié)構(gòu)中出現(xiàn)多義性的方法。
每個(gè)非虛擬對(duì)象包含在基類(lèi)中定義的數(shù)據(jù)成員的一個(gè)副本。這種重復(fù)浪費(fèi)了空間,并要求您在每次訪問(wèn)基類(lèi)成員時(shí)都必須指定所需的基類(lèi)成員的副本。
當(dāng)將某個(gè)基類(lèi)指定為虛擬基時(shí),該基類(lèi)可以多次作為間接基而無(wú)需復(fù)制其數(shù)據(jù)成員?;?lèi)的數(shù)據(jù)成員的單個(gè)副本由將其用作虛擬基的所有基類(lèi)共享。
當(dāng)聲明虛擬基類(lèi)時(shí),virtual 關(guān)鍵字將顯示在派生類(lèi)的基列表中。
請(qǐng)考慮下圖中的類(lèi)層次結(jié)構(gòu),它演示了模擬的午餐排隊(duì)。

2016122151745945.jpeg (247×104)

模擬午餐排隊(duì)圖
在該圖中,Queue 是 CashierQueue 和 LunchQueue 的基類(lèi)。但是,當(dāng)將這兩個(gè)類(lèi)組合成 LunchCashierQueue 時(shí),會(huì)出現(xiàn)以下問(wèn)題:新類(lèi)包含類(lèi)型 Queue 的兩個(gè)子對(duì)象,一個(gè)來(lái)自 CashierQueue,另一個(gè)來(lái)自 LunchQueue。下圖顯示了概念上的內(nèi)存布局(實(shí)際物理內(nèi)存布局可能會(huì)進(jìn)行優(yōu)化)。

2016122151836084.jpeg (183×119)

模擬午餐排隊(duì)對(duì)象
請(qǐng)注意,Queue 對(duì)象中有兩個(gè) LunchCashierQueue 子對(duì)象。以下代碼將 Queue 聲明為虛擬基類(lèi):

// deriv_VirtualBaseClasses.cpp
// compile with: /LD
class Queue {};
class CashierQueue : virtual public Queue {};
class LunchQueue : virtual public Queue {};
class LunchCashierQueue : public LunchQueue, public CashierQueue {};

virtual 關(guān)鍵字可確保只包含子對(duì)象 Queue 的一個(gè)副本(請(qǐng)參閱下圖)。

2016122151856486.jpeg (306×80)

使用虛擬基類(lèi)模擬午餐排隊(duì)對(duì)象
一個(gè)類(lèi)可以同時(shí)具有一個(gè)給定類(lèi)型的虛擬組件和非虛擬組件。下圖演示了這種情況。

2016122151949864.jpeg (442×190)

同一個(gè)類(lèi)的虛擬組件與非虛擬組件
在圖中,CashierQueue 和 LunchQueue 將 Queue 用作虛擬基類(lèi)。但是,TakeoutQueue 將 Queue 指定為基類(lèi)而不是虛擬基類(lèi)。因此,LunchTakeoutCashierQueue 具有類(lèi)型 Queue 的兩個(gè)子對(duì)象:一個(gè)來(lái)自包含 LunchCashierQueue 的繼承路徑,另一個(gè)來(lái)自包含 TakeoutQueue 的路徑。下圖對(duì)此進(jìn)行了演示。

2016122152012278.jpeg (478×104)

帶虛擬和非虛擬繼承的對(duì)象布局
注意
與非虛擬繼承相比較,虛擬繼承提供了顯著的大小優(yōu)勢(shì)。但是,它可能會(huì)引入額外的處理開(kāi)銷(xiāo)。
如果派生類(lèi)重寫(xiě)它從虛擬基類(lèi)繼承的虛函數(shù),并且派生基類(lèi)的構(gòu)造函數(shù)或析構(gòu)函數(shù)使用指向虛擬基類(lèi)的指針調(diào)用該虛函數(shù),則編譯器可能會(huì)將其他隱藏的“vtordisp”字段引入到具有虛擬基的類(lèi)中。/vd0 編譯器選項(xiàng)將禁止添加隱藏的 vtordisp 構(gòu)造函數(shù)/析構(gòu)函數(shù)置換成員。默認(rèn)的 /vd1 編譯器選項(xiàng)會(huì)在必要時(shí)啟用它們。僅當(dāng)確定所有類(lèi)構(gòu)造函數(shù)和析構(gòu)函數(shù)以虛擬方式調(diào)用虛函數(shù)時(shí)才關(guān)閉 vtordisps。
/vd 編譯器選項(xiàng)會(huì)影響整個(gè)編譯模塊。使用 vtordisp 雜注可以逐個(gè)類(lèi)地禁用 vtordisp 字段,然后重新啟用這些字段:

#pragma vtordisp( off )
class GetReal : virtual public { ... };
#pragma vtordisp( on )

對(duì)于前面的類(lèi)聲明,如下所示的代碼是不明確的,因?yàn)?b 所指的 b 是在 A 中還是在 B 中并不清楚:

C *pc = new C;

pc->b();

名稱(chēng)多義性
多重繼承使得沿多個(gè)路徑繼承名稱(chēng)成為可能。沿這些路徑的類(lèi)成員名稱(chēng)不一定是唯一的。這些名稱(chēng)沖突稱(chēng)為“多義性”。
任何引用類(lèi)成員的表達(dá)式必須采用明確的引用。以下示例說(shuō)明如何產(chǎn)生多義性:

// deriv_NameAmbiguities.cpp
// compile with: /LD
// Declare two base classes, A and B.
class A {
public:
 unsigned a;
 unsigned b();
};

class B {
public:
 unsigned a(); // Note that class A also has a member "a"
 int b();  // and a member "b".
 char c;
};

// Define class C as derived from A and B.
class C : public A, public B {};

請(qǐng)看前面的示例。由于名稱(chēng) a 是類(lèi) A 和類(lèi) B 的成員,因此編譯器無(wú)法辯明哪個(gè) a 指定將調(diào)用函數(shù)。如果成員可以引用多個(gè)函數(shù)、對(duì)象、類(lèi)型或枚舉數(shù),則對(duì)該成員的訪問(wèn)是不明確的。
編譯器通過(guò)按此順序執(zhí)行測(cè)試來(lái)檢測(cè)多義性:
如果對(duì)名稱(chēng)的訪問(wèn)是不明確的(如上所述),則會(huì)生成錯(cuò)誤消息。
如果重載函數(shù)是明確的,則將解析它們。(有關(guān)函數(shù)重載多義性的詳細(xì)信息,請(qǐng)參閱參數(shù)匹配。)
如果對(duì)名稱(chēng)的訪問(wèn)違背了成員訪問(wèn)權(quán)限,則會(huì)生成錯(cuò)誤消息。(有關(guān)詳細(xì)信息,請(qǐng)參閱成員訪問(wèn)控制。)
在表達(dá)式通過(guò)繼承產(chǎn)生多義性時(shí),您可以通過(guò)限定考慮中的名稱(chēng)及其類(lèi)名來(lái)手動(dòng)消除該多義性。若要適當(dāng)編譯上面的示例而不產(chǎn)生多義性,請(qǐng)使用如下代碼:

C *pc = new C;

pc->B::a();

注意
在聲明 C 時(shí),如果在 B 的范圍內(nèi)引用 C,則可能會(huì)導(dǎo)致出現(xiàn)錯(cuò)誤。但不會(huì)發(fā)出任何錯(cuò)誤,直到在 B 的范圍內(nèi)實(shí)際創(chuàng)建對(duì) C 的非限定引用。
主導(dǎo)
通過(guò)一個(gè)繼承關(guān)系圖到達(dá)多個(gè)名稱(chēng)(函數(shù)、對(duì)象或枚舉器)是可能的。這種情況被視為與非虛擬基類(lèi)一起使用時(shí)目的不明確。這些名稱(chēng)與虛擬基類(lèi)一起使用時(shí)目的不明確,除非其中一個(gè)名稱(chēng)“決定”其他名稱(chēng)。
如果某個(gè)名稱(chēng)在兩個(gè)類(lèi)中定義并且一個(gè)類(lèi)派生自另一個(gè)類(lèi),則該名稱(chēng)可控制另一個(gè)名稱(chēng)?;鶞?zhǔn)名稱(chēng)是派生類(lèi)中的名稱(chēng);此名稱(chēng)在本應(yīng)出現(xiàn)多義性時(shí)使用,如以下示例所示:

// deriv_Dominance.cpp
// compile with: /LD
class A {
public:
 int a;
};

class B : public virtual A {
public:
 int a();
};

class C : public virtual A {};

class D : public B, public C {
public:
 D() { a(); } // Not ambiguous. B::a() dominates A::a.
};

不明確的轉(zhuǎn)換
從指向類(lèi)類(lèi)型的指針或?qū)︻?lèi)類(lèi)型的引用的顯式或隱式轉(zhuǎn)換可能會(huì)導(dǎo)致多義性。下圖(指向基類(lèi)的指針的不明確轉(zhuǎn)換)顯示如下內(nèi)容:
D 類(lèi)型的對(duì)象的聲明。
將 address-of 運(yùn)算符 (&) 應(yīng)用于該對(duì)象的效果。請(qǐng)注意,address-of 運(yùn)算符總是提供該對(duì)象的基址。
將使用 address-of 運(yùn)算符獲取的指針顯式轉(zhuǎn)換為基類(lèi)類(lèi)型 A 的效果。請(qǐng)注意,將該對(duì)象的地址強(qiáng)制轉(zhuǎn)換為 A* 類(lèi)型并不總是為編譯器提供足夠的信息,以供 A 類(lèi)型的子對(duì)象進(jìn)行選擇;在這種情況下,將存在兩個(gè)子對(duì)象。

2016122152113612.jpeg (244×138)

指針到基類(lèi)的不明確轉(zhuǎn)換
到類(lèi)型 A*(指向 A 的指針)的轉(zhuǎn)換是不明確的,因?yàn)闊o(wú)法辯明 A 類(lèi)型的哪個(gè)子對(duì)象是正確的。請(qǐng)注意,您可以通過(guò)顯式指定要使用的子對(duì)象來(lái)避免多義性,如下所示:

(A *)(B *)&d  // Use B subobject.
(A *)(C *)&d  // Use C subobject.

多義性和虛擬基類(lèi)
如果使用虛擬基類(lèi),則函數(shù)、對(duì)象、類(lèi)型和枚舉數(shù)可通過(guò)多重繼承路徑到達(dá)。因?yàn)閮H有一個(gè)基類(lèi)實(shí)例,因此在訪問(wèn)這些名稱(chēng)時(shí)不存在二義性。
下圖顯示如何使用虛擬和非虛擬繼承構(gòu)成對(duì)象。

2016122152617748.jpeg (382×146)

虛擬和非虛擬派生
在該圖中,通過(guò)非虛擬基類(lèi)訪問(wèn)類(lèi) A 的任何成員都將導(dǎo)致二義性;編譯器沒(méi)有解釋是使用與 B 關(guān)聯(lián)的子對(duì)象還是與 C 關(guān)聯(lián)的子對(duì)象的信息。但是,將 A 指定為虛擬基類(lèi)時(shí),訪問(wèn)哪一個(gè)子對(duì)象都不成問(wèn)題。

相關(guān)文章

  • 使用C++ Matlab中的lp2lp函數(shù)教程詳解

    使用C++ Matlab中的lp2lp函數(shù)教程詳解

    本文介紹如何使用C++編寫(xiě)數(shù)字濾波器設(shè)計(jì)算法,實(shí)現(xiàn)Matlab中的lp2lp函數(shù),將低通濾波器轉(zhuǎn)換為參數(shù)化的低通濾波器,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-04-04
  • C++九種排序具體實(shí)現(xiàn)代碼

    C++九種排序具體實(shí)現(xiàn)代碼

    這篇文章主要介紹了C++九種排序具體實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • C++ socket實(shí)現(xiàn)miniFTP

    C++ socket實(shí)現(xiàn)miniFTP

    這篇文章主要為大家詳細(xì)介紹了C++ socket實(shí)現(xiàn)miniFTP的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • VScode中使用Cmake遇到的問(wèn)題及其解決方法(推薦)

    VScode中使用Cmake遇到的問(wèn)題及其解決方法(推薦)

    這篇文章主要介紹了VScode中使用Cmake遇到的問(wèn)題及其解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • C++ 數(shù)據(jù)結(jié)構(gòu)之水洼的數(shù)量算法

    C++ 數(shù)據(jù)結(jié)構(gòu)之水洼的數(shù)量算法

    這篇文章主要介紹了C++ 數(shù)據(jù)結(jié)構(gòu)之水洼的數(shù)量算法的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • c++類(lèi)構(gòu)造函數(shù)詳解

    c++類(lèi)構(gòu)造函數(shù)詳解

    這篇文章主要介紹了c++類(lèi)構(gòu)造函數(shù)示例,需要的朋友可以參考下
    2014-05-05
  • 380行C++代碼實(shí)現(xiàn)掃雷小游戲

    380行C++代碼實(shí)現(xiàn)掃雷小游戲

    這篇文章主要為大家詳細(xì)介紹了380行C++代碼實(shí)現(xiàn)掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • c++運(yùn)算符重載基礎(chǔ)知識(shí)詳解

    c++運(yùn)算符重載基礎(chǔ)知識(shí)詳解

    運(yùn)算符重載是一種形式的C++多態(tài)。運(yùn)算符重載將重載的概念擴(kuò)展到運(yùn)算符上,允許賦予C++運(yùn)算符多種含義
    2014-03-03
  • C++/GoLang如何實(shí)現(xiàn)自底向上的歸并排序

    C++/GoLang如何實(shí)現(xiàn)自底向上的歸并排序

    這篇文章主要給大家介紹了關(guān)于C++/GoLang如何實(shí)現(xiàn)自底向上的歸并排序的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • C?語(yǔ)言注釋和變量使用基礎(chǔ)詳解

    C?語(yǔ)言注釋和變量使用基礎(chǔ)詳解

    這篇文章主要為大家介紹了C語(yǔ)言注釋和變量使用示例基礎(chǔ)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12

最新評(píng)論