圖文例解C++類的多重繼承與虛擬繼承

在過去的學習中,我們始終接觸的單個類的繼續,但是在現實生活中,一些新事物往往會擁有兩個或者兩個以上事物的屬性,爲了解決這個問題,C++引入了多重繼續的概念,C++答應爲一個派生類指定多個基類,這樣的繼續結構被稱做多重繼續。 舉個例子,交通工具類可以派生出汽車和船連個子類,但擁有汽車和船共同特性水陸兩用汽車就必須繼續來自汽車類與船類的共同屬性。

由此我們不難想出如下的圖例與代碼:

圖文例解C++類的多重繼承與虛擬繼承

當一個派生類要使用多重繼續的時候,必須在派生類名和冒號之後列出所有基類的類名,並用逗好分隔。//程序作者:管甯

//站點:www.cndev-lab.com

//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>

using namespace std;

class Vehicle

{

public:

Vehicle(int weight = 0)

{

Vehicle::weight = weight;

}

void SetWeight(int weight)

{

cout<<"重新設置重量"<<endl;

Vehicle::weight = weight;

}

virtual void ShowMe() = 0;

PRotected:

int weight;

};

class Car:public Vehicle//汽車

{

public:

Car(int weight=0,int aird=0):Vehicle(weight)

{

Car::aird = aird;

}

void ShowMe()

{

cout<<"我是汽車!"<<endl;

}

protected:

int aird;

};

class Boat:public Vehicle//船

{

public:

Boat(int weight=0,float tonnage=0):Vehicle(weight)

{

Boat::tonnage = tonnage;

}

void ShowMe()

{

cout<<"我是船!"<<endl;

}

protected:

float tonnage;

};

class AmphibianCar:public Car,public Boat//水陸兩用汽車,多重繼續的體現

{

public:

AmphibianCar(int weight,int aird,float tonnage)

:Vehicle(weight),Car(weight,aird),Boat(weight,tonnage)

//多重繼續要注重調用基類構造函數

{

}

void ShowMe()

{

cout<<"我是水陸兩用汽車!"<<endl;

}

};

int main()

{

AmphibianCar a(4,200,1.35f);//錯誤

a.SetWeight(3);//錯誤

system("pause");

}上面的代碼從表面看,看不出有明顯的語發錯誤,但是它是不能夠通過編譯的。這有是爲什麽呢?

這是由于多重繼續帶來的繼續的模糊性帶來的問題。

圖文例解C++類的多重繼承與虛擬繼承
更多內容請看C/C++技術專題專題,或

先看如下的圖示:

圖文例解C++類的多重繼承與虛擬繼承

在圖中深紅色標記出來的地方正是主要問題所在,水陸兩用汽車類繼續了來自Car類與Boat類的屬性與方法,Car類與Boat類同爲AmphibianCar類的基類,在內存分配上AmphibianCar獲得了來自兩個類的SetWeight()成員函數,當我們調用a.SetWeight(3)的時候計算機不知道如何選擇分別屬于兩個基類的被重複擁有了的類成員函數SetWeight()。 由于這種模糊問題的存在同樣也導致了AmphibianCar a(4,200,1.35f);執行失敗,系統會産生Vehicle”不是基或成員的錯誤。以上面的代碼爲例,我們要想讓AmphibianCar類既獲得一個Vehicle的拷貝,而且又同時共享用Car類與Boat類的數據成員與成員函數就必須通過C++所提供的虛擬繼續技術來實現。我們在Car類和Boat類繼續Vehicle類出,在前面加上virtual要害字就可以實現虛擬繼續,使用虛擬繼續後,當系統碰到多重繼續的時候就會自動先加入一個Vehicle的拷貝,當再次請求一個Vehicle的拷貝的時候就會被忽略,保證繼續類成員函數的唯一性。

修改後的代碼如下,注重觀察變化://程序作者:管甯

//站點:www.cndev-lab.com

//所有稿件均有版權,如要轉載,請務必聞名出處和作者

#include <iostream>

using namespace std;

class Vehicle

{

public:

Vehicle(int weight = 0)

{

Vehicle::weight = weight;

cout<<"載入Vehicle類構造函數"<<endl;

}

void SetWeight(int weight)

{

cout<<"重新設置重量"<<endl;

Vehicle::weight = weight;

}

virtual void ShowMe() = 0;

protected:

int weight;

};

class Car:virtual public Vehicle//汽車,這裏是虛擬繼續

{

public:

Car(int weight=0,int aird=0):Vehicle(weight)

{

Car::aird = aird;

cout<<"載入Car類構造函數"<<endl;

}

void ShowMe()

{

cout<<"我是汽車!"<<endl;

}

protected:

int aird;

};

class Boat:virtual public Vehicle//船,這裏是虛擬繼續

{

public:

Boat(int weight=0,float tonnage=0):Vehicle(weight)

{

Boat::tonnage = tonnage;

cout<<"載入Boat類構造函數"<<endl;

}

void ShowMe()

{

cout<<"我是船!"<<endl;

}

protected:

float tonnage;

};

class AmphibianCar:public Car,public Boat//水陸兩用汽車,多重繼續的體現

{

public:

AmphibianCar(int weight,int aird,float tonnage)

:Vehicle(weight),Car(weight,aird),Boat(weight,tonnage)

//多重繼續要注重調用基類構造函數

{

cout<<"載入AmphibianCar類構造函數"<<endl;

}

void ShowMe()

{

cout<<"我是水陸兩用汽車!"<<endl;

}

void ShowMembers()

{

cout<<"重量:"<<weight<<"頓,"<<"空氣排量:"<<aird<<"CC,"<<"排水量:"<<tonnage<<"頓"<<endl;

}

};

int main()

{

AmphibianCar a(4,200,1.35f);

a.ShowMe();

a.ShowMembers();

a.SetWeight(3);

a.ShowMembers();

system("pause");

}注重觀察類構造函數的構造順序。

雖然說虛擬繼續與虛函數有一定相似的地方,但讀者務必要記住,他們之間是絕對沒有任何聯系的!

圖文例解C++類的多重繼承與虛擬繼承
更多內容請看C/C++技術專題專題,或

C++類的繼承與多重繼承的訪問控制
  在前面的練習中我們一直在使用public的繼續方式,即共有繼續方式,對于PRotected和private繼續方式,即保護繼續與私有繼續方式我們並沒有討論。 ...查看完整版>>C++類的繼承與多重繼承的訪問控制
 
C++學習手記(二)——類的繼承與派生
C++學習手記(二)——類的繼承與派生 陳根發 由于類與對象的存在,使得C++變得具有更強大的生命力,這也是C++産生的原因之一。但是C++面對對象的魔力...查看完整版>>C++學習手記(二)——類的繼承與派生
 
Microsoft Visual C++虛擬多繼承 對象模型初步分析
         Microsoft Visual C++虛擬多繼承 對象模型初步分析 狄駿鋒 2004/8/25 ...查看完整版>>Microsoft Visual C++虛擬多繼承 對象模型初步分析
 
C++箴言:絕不重定義繼承的非虛擬函數
作者: fatalerror99       出處:BLOG   假設我告訴你 class(類)D 從 class(類)B publicly derived(公有繼承),而且在 class(類)B 中定義了一個 public member func...查看完整版>>C++箴言:絕不重定義繼承的非虛擬函數
 
C++程序設計例解(04)
04. 試從含有n個int型數的數組中刪去若幹個成分,使剩下的全部成分構成一個不減的子序列。設計算法和編寫程序求出數組的不減子序列的長。 解: 從數組的第一個元素開始,順序考察數組的每個元素,當數組的全部元素都...查看完整版>>C++程序設計例解(04)
 
vb.net類的封裝,繼承,多態,抽象之一
封裝就是把各種方法和變量合並到一個類,用這個類代表某個對象爲完成一定的任務所能保存的範圍以及它能執行的操作。繼承就是根據現有類的方法和成員變量生成新的類的功能多態就是對象隨著程序執行而使其形式發生改變...查看完整版>>vb.net類的封裝,繼承,多態,抽象之一
 
簡單的理解 類的繼承 和 多態性
/* * Created on 2004-8-31 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates *//** * @author diyer6 * * TODO To change the templa...查看完整版>>簡單的理解 類的繼承 和 多態性
 
簡單的理解類的繼承和多態性
  /*  * Created on 2004-8-31  *  * TODO To change the template for this generated file go to  * Window - Preferences - Java - Code Style - Code Templates  */    /**  * @author diyer6...查看完整版>>簡單的理解類的繼承和多態性
 
Java的“多重繼承”
Java的“多重繼承”
  接口只是比抽象類“更純”的一種形式。它的用途並不止那些。由于接口根本沒有具體的實施細節——也就是說,沒有與存儲空間與“接口”關聯在一起——所以沒有任何辦法可以防止多個接口合並到一起。這一點是至關重...查看完整版>>Java的“多重繼承”
 
 
回到王朝網路首頁