C++中虛擬繼承的概念 為了解決從不同途徑繼承來的同名的數(shù)據(jù)成員在內(nèi)存中有不同的拷貝造成數(shù)據(jù)不一致問題,將共同基類設(shè)置為虛基類。這時從不同的路徑繼承過來的同名數(shù)據(jù)成員在內(nèi)存中就只有一個拷貝,同一個函數(shù)名也只有一個映射。這樣不僅就解決了二義性問題,也節(jié)省了內(nèi)存,避免了數(shù)據(jù)不一致的問題。
C++虛擬繼承 ◇概念: C++使用虛擬繼承(Virtual Inheritance),解決從不同途徑繼承來的同名的數(shù)據(jù)成員在內(nèi)存中有不同的拷貝造成數(shù)據(jù)不一致問題,將共同基類設(shè)置為虛基類。這時從不同的路徑繼承過來的同名數(shù)據(jù)成員在內(nèi)存中就只有一個拷貝,同一個函數(shù)名也只有一個映射。
◇解決問題: 解決了二義性問題,也節(jié)省了內(nèi)存,避免了數(shù)據(jù)不一致的問題。 ◇同義詞: 虛基類(把一個動詞當成一個名詞而已) 當在多條繼承路徑上有一個公共的基類,在這些路徑中的某幾條匯合處,這個公共的基類就會產(chǎn)生多個實例(或多個副本),若只想保存這個基類的一個實例,可以將這個公共基類說明為虛基類。 ◇語法: class 派生類: virtual 基類1,virtual 基類2,...,virtual 基類n { ...//派生類成員聲明 };
◇執(zhí)行順序 首先執(zhí)行虛基類的構(gòu)造函數(shù),多個虛基類的構(gòu)造函數(shù)按照被繼承的順序構(gòu)造; 執(zhí)行基類的構(gòu)造函數(shù),多個基類的構(gòu)造函數(shù)按照被繼承的順序構(gòu)造; 執(zhí)行成員對象的構(gòu)造函數(shù),多個成員對象的構(gòu)造函數(shù)按照申明的順序構(gòu)造; 執(zhí)行派生類自己的構(gòu)造函數(shù); 析構(gòu)以與構(gòu)造相反的順序執(zhí)行; mark 從虛基類直接或間接派生的派生類中的構(gòu)造函數(shù)的成員初始化列表中都要列出對虛基類構(gòu)造函數(shù)的調(diào)用。但只有用于建立對象的最派生類的構(gòu)造函數(shù)調(diào)用虛基類的構(gòu)造函數(shù),而該派生類的所有基類中列出的對虛基類的構(gòu)造函數(shù)的調(diào)用在執(zhí)行中被忽略,從而保證對虛基類子對象只初始化一次。 在一個成員初始化列表中同時出現(xiàn)對虛基類和非虛基類構(gòu)造函數(shù)的調(diào)用時,虛基類的構(gòu)造函數(shù)先于非虛基類的構(gòu)造函數(shù)執(zhí)行。
◇因果: 多重繼承->二義性->虛擬繼承解決 為什么要引入虛擬繼承 虛擬繼承是多重繼承中特有的概念。虛擬基類是為解決多重繼承而出現(xiàn)的。如:類D繼承自類B1、B2,而類B1、B2都繼承自類A,因此在類D中兩次出現(xiàn)類A中的變量和函數(shù)。為了節(jié)省內(nèi)存空間,可以將B1、B2對A的繼承定義為虛擬繼承,而A就成了虛擬基類。實現(xiàn)的代碼如下: class A class B1:public virtual A; class B2:public virtual A; class D:public B1,public B2; 虛擬繼承在一般的應(yīng)用中很少用到,所以也往往被忽視,這也主要是因為在C++中,多重繼承是不推薦的,也并不常用,而一旦離開了多重繼承,虛擬繼承就完全失去了存在的必要因為這樣只會降低效率和占用更多的空間。 引入虛繼承和直接繼承會有什么區(qū)別呢 由于有了間接性和共享性兩個特征,所以決定了虛繼承體系下的對象在訪問時必然會在時間和空間上與一般情況有較大不同。 時間:在通過繼承類對象訪問虛基類對象中的成員(包括數(shù)據(jù)成員和函數(shù)成員)時,都必須通過某種間接引用來完成,這樣會增加引用尋址時間(就和虛函數(shù)一樣),其實就是調(diào)整this指針以指向虛基類對象,只不過這個調(diào)整是運行時間接完成的。 空間:由于共享所以不必要在對象內(nèi)存中保存多份虛基類子對象的拷貝,這樣較之多繼承節(jié)省空間。虛擬繼承與普通繼承不同的是,虛擬繼承可以防止出現(xiàn)diamond繼承時,一個派生類中同時出現(xiàn)了兩個基類的子對象。也就是說,為了保證這一點,在虛擬繼承情況下,基類子對象的布局是不同于普通繼承的。因此,它需要多出一個指向基類子對象的指針。
??嫉腃++虛擬繼承 第一種情況: 第二種情況: 第三種情況 第四種情況:
class a class a class a class a { { { { virtual void func(); virtual void func(); virtual void func(); virtual void func(); }; }; char x; char x; class b:public virtual a class b :public a }; }; { { class b:public virtual a class b:public a virtual void foo(); virtual void foo(); { { }; }; virtual void foo(); virtual void foo(); }; };
|
|