1. 程式人生 > >鉆石(菱形)繼承和虛基類

鉆石(菱形)繼承和虛基類

pan 由於 test 聲明 16px pri 技術分享 color protect

鉆石(菱形)繼承

技術分享圖片

如圖,B,C繼承了A,D繼承了B,C

在這種情況下,如果D類的對象通過B、C兩個不同的作用域調用A的數據成員,將會產生兩個

不同的A的數據成員值

如下(Grandfather對應A,a是其公有數據成員,Father1,Father2對應B、C,son對應D的對象,)

技術分享圖片

可以看到有兩個不一樣的a存在,說明在賦值過程中Father1,Father2分別調用Grandfather產生兩個a

從其運行結果也可以看出來

技術分享圖片

如果son對象僅想產生一個數據成員a,則必須對Grandfather進行虛繼承

//Test1.h
#include<iostream>
using namespace
std; class Grandfather { public: int a; Grandfather(int _a):a(_a) { cout<<"Grandfather was built. "<<endl; } ~Grandfather(){cout<<"Grandfather was free. "<<endl;} }; class Father1 : public virtual Grandfather { public: int n; Father1(int _a) : n(_a),Grandfather(_a) { cout
<<"Father1 was built. "<<endl; } ~Father1(){cout<<"Father1 was free. "<<endl;} }; class Father2 : virtual public Grandfather //virtual寫在public前後都可以 { public: int n; Father2(int _a) : n(_a),Grandfather(_a) { cout<<"Father2 was built. "<<endl; }
~Father2(){cout<<"Father2 was free. "<<endl;} }; class Son : public Father1, public Father2 { public: Son(int _a):Father1(_a),Father2(_a),Grandfather(_a) { cout<<"Son was built. "<<endl; } ~Son(){cout<<"Son was free. "<<endl;} };

虛繼承就是在繼承符(public、protected、private)前或後加上virtual關鍵字,被虛繼承的類也叫虛基類

在派生類對象的創建中,

首先是虛基類的構造函數並按他們聲明順序構造。

第二批是非虛基類的構造函數按他們聲明的順序調用

第三批是成員對象的構造函數

最後是派生類自己的構造函數。

#include"Test1.h"
void main()
{
    Son son(10);
    son.Father1::n = 1;
    son.Father2::n = 2;//由於在Father1,Father2內均存在公有數據n,在對其賦值時需要加上作用域
    son.Father1::a = 5;
    son.Father2::a = 6;//兩次賦值均對一個數據成員操作
}

技術分享圖片

可以看到兩個數據成員的地址相同。

運行結果

技術分享圖片

析構順序和構造順序相反。

鉆石(菱形)繼承和虛基類