欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解C++中的菱形繼承問題

 更新時間:2023年08月08日 10:54:07   作者:悲傷的魚香肉絲er  
這篇文章主要介紹了詳解C++中的菱形繼承問題,在多繼承結(jié)構(gòu)中,存在著很多問題,比如從不同基類中繼承了同名成員,派生類中也定義了同名成員,這種二義性問題很好解決,加上要訪問的基類的類名限制就可以了,需要的朋友可以參考下

一、多重繼承或多繼承

由多個基類共同派生出新的類,這樣的繼承結(jié)構(gòu)被稱為多重繼承或多繼承。舉個例子:

#include<iostream>
using namespace std;
class fuelEngine //燃油引擎
{
private:
	int cylindenum;//汽缸數(shù)
public:
	fuelEngine(int c = 4):cylindenum(c){}
	~fuelEngine(){}
	void start(){}
};
class electricEngine//電動引擎
{
private:
	float power;
public:
	electricEngine(float p=60):power(p){}
	~electricEngine(){}
	void Start(){}
};
class Hybirdcar:public fuelEngine,public electricEngine//混動汽車
{
public:
	Hybirdcar(int c,int p):fuelEngine(c),electricEngine(p){}
	~Hybirdcar(){}
};

混動汽車類是由電動引擎類和燃油引擎類共同派生出來的派生類,這種繼承結(jié)構(gòu)就為多繼承。

二、菱形繼承(二義性和數(shù)據(jù)冗余問題)

在多繼承結(jié)構(gòu)中,存在著很多問題,比如從不同基類中繼承了同名成員,派生類中也定義了同名成員,這種二義性問題很好解決,加上要訪問的基類的類名限制就可以了,例:

#include<iostream>
using namespace std;
class Base1
{
  public:
    int var;
    void fun()
    {
        cout<<"Member of Base1"<<endl;
    }
};
class Base2
{
  public:
    int var;
    void fun()
    {
        cout<<"Member of Base2"<<endl;
    }
};
class Derived:public Base1,public Base2
{
  public:
    int var;
    void fun(){cout<<"Member of Derived"<<endl;}
};
int main()
{
    Derived d;
    Derived *p = &d;
    //訪問Derived類成員
    d.var =1;
    d.fun();
    //訪問Base1基類成員
    d.Base1::var=2;
    d.Base1::fun();
    //訪問Base2基類成員
    p->Base2::var=3;
    p->Base2::fun();
    return 0;
}

而在多繼承中還存在一種特殊情況——菱形繼承。我們還是用一段代碼來舉例說明菱形繼承:

#include<iostream>
using namespace std;
class Person
{
private:
	int _idPerson;
public:
	Person(int id) :_idPerson(id) { cout << "Create Person" << endl; }
	~Person(){}
};
class Student:public Person//學(xué)生
{
private:
	int _snum;
public:
	Student(int id,int s):Person(id),_snum(s){}
	~Student(){}
};
class Employee:public Person//職工
{
private:
	int _enum;
public:
	Employee(int id,int e):Person(id),_enum(e){}
	~Employee(){}
};
class GStudent:public Student//研究生
{
private:
	int _gsnum;
public:
	GStudent(int g,int s,int id):Student(s,id),_gsnum(g){}
	~GStudent(){}
};
class EGStudent :public GStudent,public Employee//在職研究生
{
private:
	int _egsnum;
public:
	EGStudent(int es,int s,int g,int e,int sid,int eid)
		:GStudent(s,g,sid),Employee(e,eid),_egsnum(es){}
	~EGStudent(){}
};
int main()
{
	EGStudent egs(1,2,3,4,5,6);
	return 0;
}

代碼中設(shè)計了Person類,由Person類派生出學(xué)生Student類和職工Employee類,Student類又向下派生出研究生GStudent類,再由GStudent類和Employee類共同派生出在職研究生EGStudent類,根據(jù)此段代碼的繼承關(guān)系可畫出示意圖 :

不難發(fā)現(xiàn),在菱形繼承中也存在二義性,并且出現(xiàn)數(shù)據(jù)冗余浪費了內(nèi)存空間,由基類Person的_idPerson身份證號有兩條路徑繼承到EGStudent類中,兩個身份證號在邏輯上是相同的,但在物理上被分配了不同的內(nèi)存空間,是兩個變量。

示例中對象egs的內(nèi)存分布圖如下:

那如何解決這種數(shù)據(jù)冗余和二義性問題呢?——虛繼承

在C++中可以把共同基類設(shè)置為虛基類,這樣從不同路徑繼承來的同名數(shù)據(jù)成員在內(nèi)存中只有一份,虛基類定義方式:class 派生類名:virtual 訪問限定符 基類類名{...};class 派生類名:訪問限定符 virtual 基類類名{...};(virtual關(guān)鍵字只對緊隨其后的基類名起作用)

在上述示例代碼中,兩個身份證號顯然是不合理的,所以我們可以把class Person 設(shè)置成虛基類,即class Student : virtual public Person {...}; 和 class Employee : virtual public Person {...}; 

菱形繼承就變成了菱形虛擬繼承。修改后代碼如下:

#include<iostream>
using namespace std;
class Person
{
private:
	int _idPerson;
public:
	Person(int id) :_idPerson(id) { cout << "Create Person" << endl; }
	~Person(){}
};
class Student:public virtual Person//學(xué)生
{
private:
	int _snum;
public:
	Student(int id,int s):Person(id),_snum(s){}
	~Student(){}
};
class Employee:public virtual Person//職工
{
private:
	int _enum;
public:
	Employee(int id,int e):Person(id),_enum(e){}
	~Employee(){}
};
class GStudent:public Student//研究生
{
private:
	int _gsnum;
public:
	GStudent(int g,int s,int id):Student(s,id),Person(id),_gsnum(g){}
	~GStudent(){}
};
class EGStudent :public GStudent,public Employee
{
private:
	int _egsnum;
public:
	EGStudent(int es,int s,int g,int e,int id)
		:GStudent(s,g,id),Employee(e,id),_egsnum(es),Person(id){}
	~EGStudent(){}
};
int main()
{
	EGStudent egs(1, 2, 3, 4, 5);
	Person* p = &egs;
	return 0;
}

三、菱形虛擬繼承

1.虛繼承中派生類對象構(gòu)造過程

在派生類對象的創(chuàng)建過程中,

首先是虛基類的構(gòu)造函數(shù)按聲明的順序進行構(gòu)造,

第二批是非虛基構(gòu)造函數(shù)按聲明順序構(gòu)造,

第三批是成員對象的構(gòu)造函數(shù),最后是派生類自己的構(gòu)造函數(shù)。

2.菱形虛擬繼承對象的內(nèi)存分布

 其實是通過兩個指針(虛基表指針)指向了一張?zhí)摶恚摶碇写娴氖瞧屏?,通過偏移量可以找到_idPerson的位置

有了多繼承,就有菱形繼承,有了菱形繼承就有了菱形虛擬繼承,底層實現(xiàn)很復(fù)雜,一般不建議設(shè)計出多繼承,否則在復(fù)雜度和性能上可能都會出現(xiàn)問題。

到此這篇關(guān)于詳解C++中的菱形繼承問題的文章就介紹到這了,更多相關(guān)C++的菱形繼承內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言線程對象和線程存儲的實現(xiàn)

    C語言線程對象和線程存儲的實現(xiàn)

    這篇文章主要介紹了C語言線程對象和線程存儲的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • C語言中自定義類型詳解

    C語言中自定義類型詳解

    大家好,本篇文章主要講的是C語言中自定義類型詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • C/C++ 中怎樣使用SetConsoleTextAttribute()函數(shù)來控制輸出字符的顏色

    C/C++ 中怎樣使用SetConsoleTextAttribute()函數(shù)來控制輸出字符的顏色

    這篇文章主要介紹了C/C++ 中如何使用SetConsoleTextAttribute()函數(shù)來控制輸出字符的顏色,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Visual Studio 2022 Preview 使用 C++20 Module的詳細過程

    Visual Studio 2022 Preview 使用 C++20 Module的詳細過程

    這篇文章主要介紹了Visual Studio 2022 Preview 使用 C++20 Module的過程,本文通過項目分析實例代碼相結(jié)合給大家介紹的非常詳細,需要的朋友可以參考下
    2021-09-09
  • 聊聊C語言中sizeof運算符的一個陷阱

    聊聊C語言中sizeof運算符的一個陷阱

    在C語言中,sizeof()是一個判斷數(shù)據(jù)類型或者表達式長度的運算符,下面這篇文章主要給大家介紹了關(guān)于C語言中sizeof運算符的一個陷阱的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-11-11
  • C++實現(xiàn)簡單射擊小游戲

    C++實現(xiàn)簡單射擊小游戲

    這篇文章主要為大家詳細介紹了C++實現(xiàn)簡單射擊小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • VS2019安裝配置MFC(安裝vs2019時沒有安裝mfc)

    VS2019安裝配置MFC(安裝vs2019時沒有安裝mfc)

    這篇文章主要介紹了VS2019安裝配置MFC(安裝vs2019時沒有安裝mfc),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • JsonCpp中double的問題解決

    JsonCpp中double的問題解決

    本文主要介紹了JsonCpp中double的問題解決,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 基于Protobuf C++ serialize到char*的實現(xiàn)方法分析

    基于Protobuf C++ serialize到char*的實現(xiàn)方法分析

    本篇文章是對Protobuf C++ serialize到char*的實現(xiàn)方法進行了詳細的分析介紹。需要的朋友參考下
    2013-05-05
  • C語言PlaySound函數(shù)使用方法

    C語言PlaySound函數(shù)使用方法

    這篇文章介紹了C語言PlaySound函數(shù)的使用方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12

最新評論