C 多重繼承相關問題

2021-06-27 09:10:54 字數 3656 閱讀 7250

分類: c++

2012-02-10 18:03

2758人閱讀收藏 

舉報c++

編譯器symbian

class

caccess

多重繼承的問題,首先想到多繼承建構函式如何處理?

symbian下是可以乙個c類多個m類多重繼承的

c++中的多繼承,建構函式處理並沒有問題,物件構造的時候按照繼承中宣告的順序呼叫多個父類的建構函式,析構函式同樣遵守單繼承中的原則。

二意性問題

如果多基類中存在同名成員,會產生二意性的問題

比如,root1類中宣告doany()介面,root2類中也宣告了doany()介面,child多承繼root1和root2,那麼如果child物件直接呼叫doany介面就會產生編譯錯誤。

深入原因??

物件值給父類指標、引用產生的二義性問題

繼續上面的例子,child物件的引用可以賦給root1和root2類引用。

如果存在void display(const root1&),void display(cont root2&)兩個介面,那麼child child;    display(child);這個呼叫也會產生二義性錯誤,編譯器不知道應該呼叫哪個介面。

名字查詢過程

查詢過程是乙個域乙個域的查詢,直到全域性域。每個類都有乙個類域。看如下示例**:

[cpp]view plain

copy

class

zooanimal ;  

class

bear : 

public

zooanimal ;  

bear bear;    bear.is_a;

如上呼叫,is_a的名字解析過程為:

1. 首先查詢bear類域,沒有找到

2. 查詢bear父類zooanimal類域,找到其宣告,名字解析成功。

bear.ival;

這個呼叫解析過程如何呢?因為bear和其父類zooanimal裡都有該成員定義。答案是按照上的順序查詢,查詢到馬上返回。

1. bear類域中查詢,找到ival宣告,解析成功,不再向下查詢。那麼父類中名字就被子類中定義遮蔽了。

需要用bear.zooanimal::ival的形式來域限定符訪問zooanimal類中成員ival,這樣編譯器直接在zooanimal類域中開始查詢名字。

看如下呼叫各名字的位置:

int ival;

int bear::mumble(int ival)

而如下名字解析會出錯:

int dval;

int bear::mumble(int ival)

解析過程如下:

1. 在bear類域中查詢,沒有找到

2. 在zooanimal類域中查詢,找到,但是因為私有成員不能訪問,編譯錯誤,不再向下查詢。

3. 因為上一步,全域性域中的名字就被遮蔽了。

多繼承中的情況

多繼承中,名字的解析的時候,對父類域的查詢是同時進行的。同時查詢root1類域和root2類域,如果發現找到兩個同樣的名字,那麼由於二義性名字解析出錯,產生編譯錯誤。

********************====更新********************====

才現上次的研究還沒有抓住多繼承問題的重點,下面來乙個新的總結:

1.    普通多繼承

類同時繼承自多個基類就是多繼承,c++支援多繼承。

但是需要注意多繼承產生的二意性問題,如果兩個基類都存在同名的成員,那麼在子類中對它的訪問就是有二義性錯誤的。名字解析過程中,同時找到兩個滿足條件的成員,這讓編譯器無法確定應該使用哪個。

其中比較典型的問題就是下面要講到的:菱形繼承問題。

2.    private、public、protected繼承

2.1  private繼承

與public繼承的不同:

²  不是父類的子型別,也就是說不能賦值給父類指標或引用。

²  介面私有化。

通常多繼承時會使用public繼承a,private繼承b的方式。

可以通過如下方式還原private基類中的成員訪問級別:

public:

//using private father func

//you can level down the access level, butcan't level up it.

using zooanimal::getlegs;//correct

但是,經過我的測試,你可以還原或降低原有的訪問級別,不能提高訪問級別。比如基類中本身是private方法,在public塊中using這個方法是編譯錯誤的。

2.2  public繼承

普通的繼承方式

2.3  protected繼承

基類所有public成員成為派生類的protected成員。

3.    菱形繼承

3.1 基本概念

菱形繼承是指:有基類a,b、c繼承自a,d多繼承自b、c,於是最終派生類d由兩條不同的繼承線繼承基類a。

這是多繼承中典型需要考慮的問題,這種情況下d的例項對基類a成員的訪問都是二義性錯誤的。

3.2 普通繼承方式中存在的問題

d物件中存在a類的2份不同的物件。

儲存2份a物件浪費空間。

a的建構函式會被呼叫2次。

引起二義性問題。

因為是2份不同的物件,2個物件中成員的值不一致。

為解決如上的種種問題,c++引用虛繼承。

4.    虛繼承

4.1  基本概念

虛繼承的基類叫做虛擬基類,無論它在派生層次中出現多少次,只有乙個共享的基類子物件被繼承。

c++ primmer書裡不建議大量使用虛繼承,會有效率問題。

4.2  構造、析構

虛繼承時,需要由最終派生類主動呼叫虛基類的建構函式,否則編譯錯誤。

因為,對於虛繼承的情況編譯器會阻止中間派生類呼叫虛基類的建構函式。

比如:在類d的例項初始過程中,d為最終派生類,b、c為中間派生類,a為虛基類。

呼叫d的建構函式前,先找到它的基類b,呼叫b的建構函式,呼叫b建構函式前找到b的基類a,發現為虛繼承關係,阻止b對a建構函式的呼叫。編譯器會確定d有沒有對a建構函式的呼叫,如沒有編譯報錯。

虛基類的建構函式最先被呼叫,然後再按宣告順序構造非虛基類。於是建構函式是:a、b、c、d呼叫順序。

析構函式是和構造相反的順序進行。

4.3  成員可視性

有如下幾種情況:

情況普通繼承

虛繼承a中的介面,未被b、c過載

二義性ok,呼叫a的介面

b過載了a的介面,c未過載

二義性ok,呼叫b的介面

b、c都過載的介面

二義性二義性

python多重繼承 多繼承相關

1 使用父類名.方法名呼叫父類方法 class parent def init self,name self.name name print parent的init方法被呼叫 class son1 parent def init self,name,age self.age age parent.i...

多重繼承 C 中的多重繼承

多重繼承是c 的一項功能,其中乙個類可以從多個類繼承。繼承類的建構函式以它們繼承的相同順序被呼叫。例如,在以下程式中,在a的建構函式之前呼叫b的建構函式。include using namespace std class a class b class c public b,public a not...

c 多重繼承

其實想寫這篇文章,是因為突然在整理論壇上的帖子的時候,突然發現乙個人問我如何才能在c 中實現多重繼承,當時我答的很隱晦,因此這裡我想補充說明一下.首先,我要說明一下,c 中是沒有類的多重繼承這個概念.要使用多重繼承必須要通過介面inte ce來完成.可是大家都知道inte ce實際上就是乙個虛函式列...