一、虛擬繼承的**
類d繼承自類c1和類c2,而c1類和c2類都繼承自類b,類d中會兩次繼承b,為了節省空間,可以將c1、c2對b的繼承定義為虛擬繼承,而b就成了虛擬基類
二、虛擬繼承與普通繼承的區別
1.書寫形式上:虛擬繼承要加虛擬關鍵字virtual
2.物件模型區別:虛擬繼承要多四個位元組空間,多的四個位元組為偏移量**的位址
普通繼承物件模型:基類部分在前-----派生類部分在後
虛擬繼承物件模型:積累部分在最底下
3.對於繼承成員的訪問形式
普通繼承:直接訪問
虛擬繼承:偏移量**位址----->偏移量**---->相對於基類的偏移量----->訪問基類物件
4.建構函式不同
普通繼承:
虛擬繼承:(1)派生類---->合成建構函式---->將偏移量**位址放物件前四個位元組
(2)多乙個引數--->1 (檢測是否為虛擬繼承)
三、虛擬繼承的應用與形式
1.虛擬繼承用來解決繼承中的二義性
2.**形式
(1)虛擬繼承格式:
class base //基類
;class derived :virtual public base //虛擬繼承
;int main()
(2)菱形虛擬繼承格式:
class b
virtual void funtest2()
public:
int _b;
};class c1:virtual public b
virtual void funtest3()
public:
int _c1;
};class c2 :virtual public b
virtual void funtest4()
public:
int _c2;
};class d : public c1, public c2
virtual void funtest7()
{}public:
int _d;
};int main()
----------//菱形虛擬繼承的物件模型
具體介紹見部落格《菱形虛擬繼承的物件模型分析》
四、類中某些成員的虛擬性
1.(1)建構函式、靜態函式、友元函式都不能虛擬;
(2)析構函式可以虛擬但不建議寫成虛擬形式
,賦值運算子過載可以虛擬但不建議寫成虛擬形式
2.各成員分析
(1)建構函式
不能虛擬; 建立物件時要呼叫建構函式,構造好後才可以查詢虛表呼叫虛函式,當建構函式給成虛函式時就要從虛表中找建構函式,但不到建構函式無法生成虛表。
(2)靜態函式
不能虛擬;
靜態函式不是成員函式,並且遮蔽了this指標,所以不能虛擬(注:只有成員函式才能給成虛函式)
(3)友元函式
不能虛擬;
友元函式不是成員函式,所以不能虛擬
(4)析構函式
可以虛擬;但是析構函式給成虛函式後,析構函式的呼叫不明確,竟導致記憶體洩露,所以建議不要給成虛函式。
(5)運算子過載
可以虛擬;但是運算子過載給成虛函式後,派生類中的運算子過載虛函式與基類中的運算子過載虛函式構成重寫,原本是想讓物件呼叫各自類自己的運算子過載,然而有時物件會只呼叫某乙個類中的運算子過載函式。所以不建議給成虛函式。
C 虛擬繼承
就是為了解決面相物件中繼承結構中可怕的菱形結構 下面是別人的,看看就懂了。從意義上來看,乙個sleepersofa沒有沙發和床兩種重量,如此的繼承不是真實的現實世界描述。進一步分析可得,床和沙發都是家具的一種,凡家具都有重量,所以通過分解來考察其關係,如圖17 2所示。圖17 2 床和沙發的分解 c...
C 虛擬繼承
就是為了解決面相物件中繼承結構中可怕的菱形結構 下面是別人的,看看就懂了。從意義上來看,乙個sleepersofa沒有沙發和床兩種重量,如此的繼承不是真實的現實世界描述。進一步分析可得,床和沙發都是家具的一種,凡家具都有重量,所以通過分解來考察其關係,如圖17 2所示。圖17 2 床和沙發的分解 c...
虛擬繼承C
c 中虛擬繼承的概念 為了解決從不同途徑繼承來的同名的資料成員在記憶體中有不同的拷貝造成資料不一致問題,將共同基類設定為虛基類。這時從不同的路徑繼承過來的同名資料成員在記憶體中就只有乙個拷貝,同乙個函式名也只有乙個對映。這樣不僅就解決了二義性問題,也節省了記憶體,避免了資料不一致的問題。class ...