目錄
1、來自不同父類的相同成員的訪問問題
2、多繼承中的鑽石繼承問題
3、鑽石繼承問題的解決方法
4、在使用虛基類的情況下,構造父類的順序問題
多繼承情況下,來自不同父類的相同成員的訪問問題 :假設子類繼承自2個父類,這兩個父類中包含有同名的(資料)成員n,這時通過物件直接來訪問該(資料)成員n時會出現什麼問題?從繼承的角度講,該資料成員將分別拷貝到子類中,那麼子類中將有兩個同名但記憶體位址不同的n。這樣,在訪問該成員時,系統將不知物件要訪問的是哪個基類的成員n(二義性,標識名n不唯一)。
解決問題的方法:通常採用作用域分辨符「::」進行唯一性標識。格式:
基類名::成員名; //資料成員
基類名::成員名(參數列); //函式成員
例如:
#includeusing namespace std;
class b1
private:
int n;
};class b2
public:
int n; //也有成員n
};class d:public b1,public b2
public:
int x;
};int main()
鑽石繼承:形如子類d繼承自b1和b2,而b1和b2分別繼承自b0,從繼承的圖示上看是個菱形結構,類似鑽石,故稱之鑽石繼承。
這種情況下,若b0的成員身份證號(id)將分別拷貝給b1和b2,那麼d也會繼承這2個同名的id成員,當然,通過作用域限定符可以訪問b1和b2中的id,但是,id號本身應該唯一,沒有必要分別給b1和b2中各拷貝乙份,id完全可以共享使用,要實現這樣的目的,需要用到虛擬繼承的方法。使用虛擬繼承(virtual)和虛基類,從不同路徑繼承來的同名資料成員在記憶體中就只有乙個拷貝,同名函式也只有一種對映,使得子類都去共享基類中的成員。這種繼承方式稱為虛擬繼承,被繼承的類稱為虛基類。
格式:
class 派生類名:virtual 訪問限定符 基類類名;
或 class 派生類名:訪問限定符 virtual 基類類名;
例如:
#includeusing namespace std;
class b0
public:
int id;
};class b1:virtual public b0 //虛基類
private:
int n;
};class b2:virtual public b0 //虛基類
public:
int n; //也有成員n
};class d: public b1, public b2
public:
int x;
};int main()
在派生類物件的建立中首先是虛基類的建構函式並按它們宣告的順序構造。第二批是非虛基類的建構函式按它們宣告的順序呼叫。第三批是成員物件的建構函式。最後是派生類自己的建構函式被呼叫.例如:
#includeusing namespace std;
class base1
;class b : virtual public a
;class c : virtual public a
;class dd : public b, public c
;int main()
d物件的記憶體布局
虛基類表
C 繼承記憶體布局 虛繼承下的多繼承情況
前面介紹了單繼承以及正常多繼承的記憶體分布情況,最後介紹一種虛繼承的情況。同時虛繼承也是解決多繼承二義性的一種手段。首先將 改動如下,base1跟base11是完全一樣的 除了繼承的時候base1是虛繼承,我們先看下單繼承的時候,虛繼承的記憶體分布跟非虛繼承有什麼區別。可以看到虛繼承的記憶體分布要複...
繼承情況下的類作用域
建構函式和析構函式中的虛函式,構造和析構也是分階段的,也就是說從無到基類物件,再到派生類物件,從派生類物件到基類物件,再到無。這中間有乙個狀態就是基類物件,此時直接或間接呼叫虛函式,只能是基類中的版本,因為後邊的還沒形成呢。因為如果使用派生類中的版本,可能需要訪問派生類物件的成員,而這些還不存在,為...
繼承情況下類的作用域
在繼承情況下,派生類的作用域巢狀在基類作用域中。因此,如果不能在派生類作用域中確定的名字,就在外圍基類作用域中查詢該名字的定義。在基類和派生類中使用同一名字的成員函式,其行為與資料成員一樣 在派生類作用域中派生類成員將遮蔽基類成員。即使函式原型不同,基類成員也會被遮蔽。如果要訪問被遮蔽的基類成員,需...