分類: 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實際上就是乙個虛函式列...