1. 程式人生 > >避免多重繼承引起的衝突——虛基類

避免多重繼承引起的衝突——虛基類

在CPP中,是允許一個基類通過不同的途徑重複繼承同一個祖先類的。這時祖先類裡面的成員就被拷貝多份,當外界想呼叫的時候編譯器無法決定使用哪一個副本,因而會報錯。
為了避免這種情況,CPP中產生了虛基類——Virtual base。

使用方法:在繼承訪問控制之前加上保留字:virtual

普通基類與虛基類之間的唯一區別只有在派生類重複繼承了某一基類時才表現出來。

舉個栗子:

class BASE {public: int i;};
class BASE1: virtual public BASE {  //由於使用了virtual這裡BASE變成了BASE1的一個虛基類。
 public
: int j; }; class BASE2: virtual public BASE { public: int k; }; class DERIVED: public BASE1, public BASE2 { public: int sum; }; int main() { DERIVED obj; // 宣告一個派生類物件 obj.i = 3; // 正確:從BASE繼承的i在DERIVED中只有一份 obj.j = 5; // 正確:使用從BASE1繼承的j obj.k = 7; // 正確:使用從BASE2繼承的k return 0; }

若派生類有一個虛基類作為祖先類,則在派生類建構函式中需要列出對虛基類建構函式的呼叫,即顯示呼叫

(否則,呼叫虛基類的預設建構函式),且對虛基類建構函式的呼叫總是先於普通基類的建構函式。
而普通基類的建構函式無需顯示呼叫,只需在引數列表之後向其傳遞引數即可。

再結合之前的建構函式的呼叫順序,感受一下下面這個例子:

#include "iostream"
using namespace std;
class baseA {
 public:
    baseA() {
        cout << endl << "This is baseA class." << endl;
    }
};

class baseB {
 public:
    baseB
() { cout << endl << "This is baseB class." << endl; } }; class derivedA : public baseB, virtual public baseA { public: derivedA() { cout << endl << "This is derivedA class." << endl; } }; class derivedB : public baseB, virtual public baseA { public: derivedB() { cout << endl << "This is derivedB class." << endl; } }; class Derived : public derivedA, virtual public derivedB { public: Derived() { cout << endl << "This is Derived class." << endl; } }; int main() { Derived obj; return 0; }

執行結果

This is baseA class.
This is baseB class.
This is derivedB class.
This is baseB class.
This is derivedA class.
This is Derived class.

相關推薦

避免多重繼承引起衝突——

在CPP中,是允許一個基類通過不同的途徑重複繼承同一個祖先類的。這時祖先類裡面的成員就被拷貝多份,當外界想呼叫的時候編譯器無法決定使用哪一個副本,因而會報錯。 為了避免這種情況,CPP中產生了虛基類——Virtual base。 使用方法:在繼承訪問控制之前

13.多重繼承(菱形繼承),繼承

多重繼承: 就是一個派生類多個基類,幾乎與單繼承是一致的。 唯一考點: 菱形繼承結構(B類C類繼承A類,D類繼承A類。),產生問題,派生類有多份基類的資料。   解決辦法:B C都採用虛繼承,只有一

C++ 多重繼承

使用多個基類的繼承被稱為多重繼承(MI)。 MI描述的是有多個直接基類的類。與單繼承一樣,公有MI表示的也是 is--a關係。 MI帶來的兩個主要問題: 1. 從兩個不同的基類繼承同名方法。 2. 從兩個或更多相關基類那裡繼承同一類的多個例項。 例如: s

多重繼承與型別轉換 -- 繼承

多重繼承是C++的特性之一,但在比較新的Java和C#中被摒棄,因為多重繼承在型別轉換中會出現一些有意思的現象。 下面是虛方法多重繼承 #include <iostream> #define interface struct using namespace st

多重繼承,菱形繼承下的虛擬函式表和

虛擬函式與虛繼承尋蹤 封裝、繼承、多型是面嚮物件語言的三大特性,熟悉C++的人對此應該不會有太多異議。C語言提供的struct,頂多算得上對資料的簡單封裝,而C++的引入把struct“升級”為cla

多重繼承的建構函式和解構函式的執行順序(包含

C++程式碼: #include <iostream> using namespace std; class A { public: A() { co

3.10 C++ 繼承

set http turn () virt public virtual 這樣的 rtu 參考:http://www.weixueyuan.net/view/6367.html 總結:     本例即為典型的菱形繼承結構,類A中的成員變量及成員函數繼承到類D中均會產生兩份,

c++筆記之&菱形繼承

簡單例子: #include <iostream> #include <string> using namespace std; class Person { public: Person(string nam, char s, int a) { n

16 More Effective C++ —— 條款23/24 (虛擬函式、、多繼承、RTTI)

0 前序 由於條款23只是針對iostream和stdio.h之間,進行執行效率的對比,此處不會詳細展開。其宗旨是儘量使用C++的庫,可以提高程式的執行效率和安全性。 此篇將著重討論條論24的內容。 1 多型 C++中,多型是指使用基類指標、引用指向派生類,若基類和派生類中,

C++:10---多級混合繼承詳解

一、多級混合繼承 下面介紹菱形繼承 //菱形繼承 class A { public: int data; }; class B:public A { public: int data; }; class C:public A { public: int data;

【程式語言】C++繼承和派生

從已有的物件型別出發建立一種新的物件型別,使它部分或全部繼承原物件的特點和功能,這是面向物件設計方法中的基本特性之一。繼承不僅簡化了程式設計方法,顯著提高了軟體的重用性,而且還使得軟體更加容易維護。派生則是繼承的直接產物,它通過繼承已有的一個或多個類來產生一個新的類,通過派生

繼承的本質(介紹的非常詳細)

      虛繼承與虛基類的本質    虛繼承和虛基類的定義是非常的簡單的,同時也是非常容易判斷一個繼承是否是虛繼承的,雖然這兩個概念的定義是非常的簡單明確的,但是在C++語言中虛繼承作為一個比較生僻的但是又是絕對必要的組成部份而存在著,並且其行為和模型均表現出和一般的繼承體

C++繼承;虛擬函式與繼承

定義:在C++中,在定義公共基類的派生類的時候,如果在繼承方式前使用關鍵字virtual對繼承方式限定,這樣的繼承方式就是虛擬繼承,公共的基類成為虛基類。這樣,在具有公共基類的、使用了虛擬繼承方式的多個派生類的公共派生類中,該基類的成員就只有一份拷貝

【c++】深入剖析虛擬繼承與各種繼承關係中派生內成員記憶體分佈情況及表的內容

概要 本文講述在VS2012環境下,採用程式碼和圖結合的方法,分析C++程式碼中不同繼承方式的物件模型,以及從彙編角度分析虛擬繼承編譯器生成的虛基類表裡的內容,不涉及虛擬函式。 繼承分類: 1.單繼承 一個子類只有一個直接父類 // 單繼承 工人類 繼承 人類 cl

C++ 繼承

//聯絡人:石虎 QQ:1224614774 暱稱:嗡嘛呢叭咪哄一、概念1.定義:在多重繼承下,一個基類可以在派生層次中出現多次。(派生類物件中可能出現多個基類物件)在 C++ 中,通過使用虛繼承解決這

C++繼承

為什麼有虛繼承 多繼承(Multiple Inheritance)是指從多個直接基類中產生派生類的能力,多繼承的派生類繼承了所有父類的成員。儘管概念上非常簡單,但是多個基類的相互交織可能會帶來錯綜複雜的設計問題,命名衝突就是不可迴避的一個。 多繼承時很容易產生命名衝

C++繼承和派生——派生成員的標識與訪問(作用域分辨符和技術)

在派生類中,成員可以按訪問屬性劃分為以下四種: 不可訪問成員 準確說是不可以直接訪問。這種成員是從基類私有成員繼承而來,派生類或者派生類物件的模組都無法訪問這些成員,當然,派生類繼續派生的新類也是無法訪問它們的。 私有成員 這個可以是從

鉆石(菱形)繼承

pan 由於 test 聲明 16px pri 技術分享 color protect 鉆石(菱形)繼承 如圖,B,C繼承了A,D繼承了B,C 在這種情況下,如果D類的對象通過B、C兩個不同的作用域調用A的數據成員,將會產生兩個 不同的A的數據成員值 如下(Grandfat

C++ 表指針字節對齊

小結 整數 影響 div 軟件測試 而已 焦點 測試 內存布局 下面博客轉載自別人的,我也是被這個問題坑了快兩天了,關於各種虛基類,虛繼承,虛函數以及數據成員等引發的一系列內存對齊的問題再次詳細描述 先看下面這片代碼。在這裏我使用了一個空類K,不要被這個東西所迷

java中接口(interface)和(abstract class)的區別

private 特定 知識庫 價值 ceo 實現 相互 定義 協調 在Java語言中,abstract class和interface是支持抽象類定義的兩種機制。正是由於這兩種機制的存在,才賦予了Java強大的面向對象能力。abstract class和interface之