最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C++中的菱形繼承問(wèn)題

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

一、多重繼承或多繼承

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

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

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

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

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

#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;
    //訪問(wèn)Derived類(lèi)成員
    d.var =1;
    d.fun();
    //訪問(wèn)Base1基類(lèi)成員
    d.Base1::var=2;
    d.Base1::fun();
    //訪問(wèn)Base2基類(lèi)成員
    p->Base2::var=3;
    p->Base2::fun();
    return 0;
}

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

#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è)計(jì)了Person類(lèi),由Person類(lèi)派生出學(xué)生Student類(lèi)和職工Employee類(lèi),Student類(lèi)又向下派生出研究生GStudent類(lèi),再由GStudent類(lèi)和Employee類(lèi)共同派生出在職研究生EGStudent類(lèi),根據(jù)此段代碼的繼承關(guān)系可畫(huà)出示意圖 :

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

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

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

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

在上述示例代碼中,兩個(gè)身份證號(hào)顯然是不合理的,所以我們可以把class Person 設(shè)置成虛基類(lèi),即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.虛繼承中派生類(lèi)對(duì)象構(gòu)造過(guò)程

在派生類(lèi)對(duì)象的創(chuàng)建過(guò)程中,

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

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

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

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

 其實(shí)是通過(guò)兩個(gè)指針(虛基表指針)指向了一張?zhí)摶?,虛基表中存的是偏移量,通過(guò)偏移量可以找到_idPerson的位置

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

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

相關(guān)文章

  • 解析shell排序的實(shí)現(xiàn)代碼

    解析shell排序的實(shí)現(xiàn)代碼

    本篇文章是對(duì)shell排序的實(shí)現(xiàn)代碼進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • OpenCV mask的作用及如何制作掩模mask

    OpenCV mask的作用及如何制作掩模mask

    mask 不是馬斯克,是掩膜,可以用來(lái)遮蓋非感興趣區(qū),突出感興趣區(qū),使得圖像處理只專注于ROI部分,OpenCV中的很多函數(shù)用到mask,mask是什么?怎么制作一個(gè)mask?本文給大家分享OpenCV mask的作用及如何制作掩模mask,感興趣的朋友一起看看吧
    2023-02-02
  • C語(yǔ)言之通訊錄的模擬實(shí)現(xiàn)代碼

    C語(yǔ)言之通訊錄的模擬實(shí)現(xiàn)代碼

    這篇文章主要介紹了C語(yǔ)言之通訊錄的模擬實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • C和C++ const的聲明差異

    C和C++ const的聲明差異

    本文給大家簡(jiǎn)單匯總了下C語(yǔ)言的const與C++的const的聲明差異,非常的簡(jiǎn)單,也很實(shí)用,有需要的小伙伴可以參考下
    2016-03-03
  • C++lambda表達(dá)式使用介紹

    C++lambda表達(dá)式使用介紹

    Lambda 表達(dá)式(lambda expression)是一個(gè)匿名函數(shù),Lambda表達(dá)式基于數(shù)學(xué)中的λ演算得名。本文就來(lái)為大家詳細(xì)講講C++中Lambda表達(dá)式的使用,需要的可以參考一下
    2022-08-08
  • Visual Studio Code 配置C、C++環(huán)境/編譯并運(yùn)行的流程分析

    Visual Studio Code 配置C、C++環(huán)境/編譯并運(yùn)行的流程分析

    這篇文章主要介紹了Visual Studio Code 配置C、C++環(huán)境/編譯并運(yùn)行的流程分析,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • C++高精度計(jì)時(shí)的幾種方法總結(jié)(測(cè)試函數(shù)運(yùn)行時(shí)間)

    C++高精度計(jì)時(shí)的幾種方法總結(jié)(測(cè)試函數(shù)運(yùn)行時(shí)間)

    本文介紹了C++中常用的幾種程序計(jì)時(shí)方法,包括clock()函數(shù)、GetTickCount()、QueryPerformanceCounter()以及C++11中的chrono庫(kù)函數(shù),這篇文章主要介紹了C++高精度計(jì)時(shí)的幾種方法,需要的朋友可以參考下
    2024-09-09
  • C++11 學(xué)習(xí)筆記之std::function和bind綁定器

    C++11 學(xué)習(xí)筆記之std::function和bind綁定器

    這篇文章主要介紹了C++11 學(xué)習(xí)筆記之std::function和bind綁定器,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-07-07
  • C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之鏈隊(duì)列的基本操作

    C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之鏈隊(duì)列的基本操作

    這篇文章主要為大家介紹了C語(yǔ)言之鏈隊(duì)列的基本操作,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-12-12
  • 解析C/C++中如何終止線程的運(yùn)行

    解析C/C++中如何終止線程的運(yùn)行

    本篇文章是對(duì)C/C++中如何終止線程運(yùn)行的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05

最新評(píng)論

常熟市| 南华县| 新丰县| 图木舒克市| 靖州| 诏安县| 历史| 来宾市| 青龙| 五河县| 南漳县| 新乡市| 田林县| 安康市| 张掖市| 洛川县| 民勤县| 旬邑县| 湟源县| 彭州市| 芦山县| 商水县| 通山县| 土默特右旗| 阳谷县| 甘肃省| 邛崃市| 和林格尔县| 边坝县| 崇左市| 原平市| 水富县| 弋阳县| 青海省| 阿拉善左旗| 五家渠市| 灵寿县| 隆安县| 吉木乃县| 收藏| 文成县|