日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++ 继承解析

發(fā)布時(shí)間:2023/12/20 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 继承解析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

繼承

?

1、概念:

繼承(inheritance)機(jī)制是面向?qū)ο蟪绦蛟O(shè)計(jì)使代碼可以復(fù)用的最重要的手段,它允許程序員在保持原有類(lèi)特性的基礎(chǔ)上進(jìn)行擴(kuò)展,增加功能。這樣產(chǎn)生新的類(lèi),稱(chēng)派生類(lèi)。繼承呈現(xiàn)了面向?qū)ο蟪绦蛟O(shè)計(jì)的層次結(jié)構(gòu),體現(xiàn)了由簡(jiǎn)單到復(fù)雜的認(rèn)知過(guò)程。

一個(gè)新類(lèi)從已有的類(lèi)中獲得其已有的特性稱(chēng)為繼承,被繼承的稱(chēng)為父類(lèi)(Base class)或基類(lèi),新產(chǎn)生的類(lèi)稱(chēng)為派生類(lèi)或子類(lèi)。

?

?

2、訪(fǎng)問(wèn)限定符與繼承關(guān)系

?

類(lèi)的成員有三種訪(fǎng)問(wèn)限定符:public(公有)、protected(保護(hù))、

private(私有)

?

繼承的方式:public(公有繼承)、protected(保護(hù)繼承)、

Private(私有繼承)

?

3、繼承的方式:

繼承權(quán)限規(guī)則表

繼承方式

基類(lèi)的public成員

基類(lèi)的protected成員

基類(lèi)的private成員

繼承引起的訪(fǎng)問(wèn)控制變化

Public

Public

Protected

不可見(jiàn)

基類(lèi)成員在派生類(lèi)中訪(fǎng)問(wèn)權(quán)限不變

Protected

Protected

Protected

不可見(jiàn)

基類(lèi)的非私有成員成為子類(lèi)的保護(hù)成員

Private

Private

Private

不可見(jiàn)

基類(lèi)的所有成員成為子類(lèi)的私有成員

?

?

基類(lèi):

class Base

{

public:

????? Base()

?????????? :pub(1)

?????????? ,pro(2)

?????????? ,pri(3)

????? {}

?

public:

????? int pub;

?

protected:

????? int pro;

?

private:

????? int pri;

?

};

?

(1)公有繼承:采用公有繼承時(shí),基類(lèi)成員的訪(fǎng)問(wèn)權(quán)限在派生類(lèi)中不變

class Derived1:public Base

{

public:

?????? Derived1()

????????????? :d_pub(4)

????????????? ,d_pro(5)

????????????? ,d_pri(6)

?????? {}

?????? void SetData()

?????? {

????????????? pub = 0;

????????????? pro = 0;

????????????? pri = 0;?? //子類(lèi)無(wú)法訪(fǎng)問(wèn)基類(lèi)的私有成員

?????? }

?

public:

?????? int d_pub;

protected:

?????? int d_pro;

private:

?????? int d_pri;

};

?

void FunTest()

{

?????? Base b;

?????? b.pub = 1;

?????? b.pro = 2;???

?????? b.pri = 3;???? ?? //類(lèi)外無(wú)法訪(fǎng)問(wèn)類(lèi)的保護(hù)、私有成員

?

?????? Derived1 d1;

?????? d1.pub = 1;

?????? d1.pro = 2;

?????? d1.pri = 3;?? //子類(lèi)對(duì)象無(wú)法訪(fǎng)問(wèn)基類(lèi)的保護(hù)、私有成員

?

?????? d1.d_pub = 4;

?????? d1.d_pro = 4;

?????? d1.d_pri = 4;???? //類(lèi)外無(wú)法訪(fǎng)問(wèn)類(lèi)的保護(hù)、私有成員

}

?

(2)保護(hù)繼承:基類(lèi)的公有、保護(hù)成員成為派生類(lèi)的保護(hù)成員。

?

class Derived2:protected Base

{

public:

?????? Derived2()

????????????? :d_pub(4)

????????????? ,d_pro(5)

????????????? ,d_pri(6)

?????? {}

?????? void SetData()

?????? {

????????????? pub = 0;? //成為子類(lèi)的保護(hù)成員

????????????? pro = 0;

????????????? pri = 0;?? //子類(lèi)無(wú)法訪(fǎng)問(wèn)基類(lèi)的私有成員

?????? }

?

public:

?????? int d_pub;

protected:

?????? int d_pro;

private:

?????? int d_pri;

};

?

void FunTest()

{

?????? Base b;

?????? b.pub = 1;

?????? b.pro = 2;???

?????? b.pri = 3;???? ?? //類(lèi)外無(wú)法訪(fǎng)問(wèn)類(lèi)的保護(hù)、私有成員

?

?????? Derived2 d2;

?????? d2.pub = 1; ? //成為子類(lèi)的保護(hù)成員,無(wú)法訪(fǎng)問(wèn)

?????? d2.pro = 2;

?????? d2.pri = 3;? //子類(lèi)對(duì)象無(wú)法訪(fǎng)問(wèn)基類(lèi)的保護(hù)、私有成員

?

?????? d2.d_pub = 4;

?????? d2.d_pro = 4;

?????? d2.d_pri = 4;???? //類(lèi)外無(wú)法訪(fǎng)問(wèn)類(lèi)的保護(hù)、私有成員

}

(3)私有繼承

class Derived3:private Base

{

public:

?????? Derived3()

????????????? :d_pub(4)

????????????? ,d_pro(5)

????????????? ,d_pri(6)

?????? {}

?????? void SetData()

?????? {

????????????? pub = 0;? //成為子類(lèi)的私有成員

????????????? pro = 0;

????????????? pri = 0;?? //子類(lèi)無(wú)法訪(fǎng)問(wèn)基類(lèi)的私有成員

?????? }

?

public:

?????? int d_pub;

protected:

?????? int d_pro;

private:

?????? int d_pri;

};

?

void FunTest()

{

?????? Base b;

?????? b.pub = 1;

?????? b.pro = 2;???

?????? b.pri = 3;???? ?? //類(lèi)外無(wú)法訪(fǎng)問(wèn)類(lèi)的保護(hù)、私有成員

?

?????? Derived3 d3;

?????? d3.pub = 1; ? //成為子類(lèi)的私有成員,無(wú)法訪(fǎng)問(wèn)

?????? d3.pro = 2;

?????? d3.pri = 3;?? //子類(lèi)對(duì)象無(wú)法訪(fǎng)問(wèn)基類(lèi)的保護(hù)、私有成員

?

?????? d3.d_pub = 4;

?????? d3.d_pro = 4;

?????? d3.d_pri = 4;???? //類(lèi)外無(wú)法訪(fǎng)問(wèn)類(lèi)的保護(hù)、私有成員

}

?

?

?

2、?總結(jié):

?

(1)??????類(lèi)的保護(hù)成員和私有成員在類(lèi)外部都不可訪(fǎng)問(wèn),基類(lèi)的私有成員在派生類(lèi)都不可訪(fǎng)問(wèn)。

?

?

(2)???public繼承是一個(gè)接口繼承,保持is-a原則,每個(gè)父類(lèi)可用的成員對(duì)子類(lèi)也可用,因?yàn)槊總€(gè)子類(lèi)對(duì)象也都是一個(gè)父類(lèi)對(duì)象。

?

例如:有一個(gè)Horse類(lèi)可以保存關(guān)于馬的所有信息,身高體重等等,那么我們就可以從Horse類(lèi)中派生出白馬類(lèi),白馬類(lèi)包含所有Horse類(lèi)的成員,在白馬類(lèi)中可以新增關(guān)于白馬的成員,這個(gè)成員通常不用于Horse類(lèi)。

?????????? class Horse

{

public:

??? int Tall;

??? int Weight;

};

classWhiteHorse:public Horse

{

public:

??? int Color;

};

WhiteHorseHorse的一個(gè)子類(lèi),包括了Horse類(lèi)的所有成員,is_a是一種關(guān)系

?

?

(3)???protetced/private繼承是一個(gè)實(shí)現(xiàn)繼承,基類(lèi)的部分成員并非完全成為子類(lèi)接口的一部分,是 has-a 的關(guān)系原則,所以非特殊情況下不會(huì)使用這兩種繼承關(guān)系,在絕大多數(shù)的場(chǎng)景下使用的都是公有繼承。

?

實(shí)現(xiàn)繼承的主要目標(biāo)是代碼重用,我們發(fā)現(xiàn)類(lèi)B和類(lèi)C存在同樣的代碼,因此我們?cè)O(shè)計(jì)了一個(gè)類(lèi) A,用于存放通用的代碼,基于這種思路的繼承稱(chēng)為實(shí)現(xiàn)繼承。?

基類(lèi)的成員在派生類(lèi)中是私有的,基類(lèi)方法將不會(huì)成為派生對(duì)象公有接口的一部分,但可以在派生類(lèi)的成員函數(shù)中使用它們,基類(lèi)方法將不會(huì)成為派生對(duì)象公有接口的一部分,但可以在派生類(lèi)的成員函數(shù)中使用它們。

?

?class Banana

{..};

class Lauch

{

private:

classBanana; ......

};

?

(4)???基類(lèi)的 private 成員在派生類(lèi)中是不能被訪(fǎng)問(wèn)的,如果基類(lèi)成員不想在類(lèi)外直接被訪(fǎng)問(wèn),但需要在派生類(lèi)中能訪(fǎng)問(wèn),就定義為 protected 。可以看出保護(hù)成員限定符是因繼承才出現(xiàn)的。

?

(5)???使用關(guān)鍵字class時(shí)默認(rèn)的繼承方式是private,使用struct時(shí)默認(rèn)的繼承方式是public,不過(guò)最好顯示的寫(xiě)出繼承方式。

?

3、?派生類(lèi)的默認(rèn)成員函數(shù)



在繼承關(guān)系里面,在派生類(lèi)中如果沒(méi)有顯示定義這六個(gè)成員函數(shù),編譯系統(tǒng)則會(huì)默認(rèn)合成這六個(gè)默認(rèn)

的成員函數(shù)。

?

(1)???構(gòu)造函數(shù)調(diào)用順序:

進(jìn)入子類(lèi)的構(gòu)造函數(shù)——>調(diào)用基類(lèi)構(gòu)造函數(shù)——>執(zhí)行子類(lèi)構(gòu)造函數(shù)

說(shuō)明:

1)、基類(lèi)沒(méi)有缺省構(gòu)造函數(shù),派生類(lèi)必須要在初始化列表中顯式給出基類(lèi)名和參數(shù)列表。

2)、基類(lèi)沒(méi)有定義構(gòu)造函數(shù),則派生類(lèi)也可以不用定義,全部使用缺省構(gòu)造函數(shù)。

3)、基類(lèi)定義了帶有形參表構(gòu)造函數(shù),派生類(lèi)就一定定義構(gòu)造函數(shù)

?

(2)??????析構(gòu)函數(shù)調(diào)用順序:

派生類(lèi)析構(gòu)函數(shù)——>派生類(lèi)包含成員對(duì)象的析構(gòu)函數(shù)——>基類(lèi)析構(gòu)函數(shù)

class Base

{

public:

?????? Base()

?????? {

????????????? ?cout<<"Base()"<<endl;

?????? }

?????? Base(int b, int r, int i)

????????????? :pub(1)

????????????? ,pro(2)

????????????? ,pri(3)

?????? {

????????????? cout<<"Base(int , int , int)"<<endl;

?????? }

?????? ~Base()

?????? {

????????????? cout<<"~Base()"<<endl;

?????? }

public:

?????? int pub;

protected:

?????? int pro;

private:

?????? int pri;

};

class Derived3:public Base

{

public:

?????? Derived3()

?????? {

????????????? ??cout<<"Derived3()"<<endl;

?????? }

?????? Derived3(int d1, int d2, int d3)

????????????? :Base(d1, d2, d3)

?????? {

????????????? d_pub = d1;

????????????? cout<<"Derived3()???----"<<"d_pub="<<d_pub<<endl;

?????? }

?????? ~ Derived3()

?????? {

????????????? cout<<"~Derived3()"<<endl;

?????? }

public:

?????? int d_pub;

protected:

?????? int d_pro;

private:

?????? int d_pri;

};

void FunTest()

{

?????? Derived3 d0;

?????? Derived3 d3(1, 2, 3);

}

?

?

?

4、即成體系中的作用域:

(1)在繼承體系中基類(lèi)和派生類(lèi)是兩個(gè)不同作用域。

(2) 子類(lèi)和父類(lèi)中有同名成員,子類(lèi)成員將屏蔽父類(lèi)對(duì)成員的直接訪(fǎng)問(wèn)。(在子類(lèi)成員函數(shù)中,可以使用 基類(lèi)::基類(lèi)成員 訪(fǎng)問(wèn))--隱藏 --重定義

(3) 注意在實(shí)際中在繼承體系里面最好不要定義同名的成員

?

5、繼承與轉(zhuǎn)換--賦值兼容規(guī)則:(public繼承)

(1)子類(lèi)對(duì)象可以賦值給父類(lèi)對(duì)象(切割/切片)

(2)父類(lèi)對(duì)象不能賦值給子類(lèi)對(duì)象

(3)父類(lèi)的指針/引用可以指向子類(lèi)對(duì)象

(4)子類(lèi)的指針/引用不能指向父類(lèi)對(duì)象(可以通過(guò)強(qiáng)制類(lèi)型轉(zhuǎn)換完成)

class Base

{

public:

?????? Base()

?????? {

????????????? ?cout<<"Base()"<<endl;

?????? }

?????? Base(int b, int r, int i)

????????????? :pub(1)

????????????? ,pro(2)

????????????? ,pri(3)

?????? { cout<<"Base(int , int , int)"<<endl; }

?????? ~Base()

?????? {cout<<"~Base()"<<endl;}

?

public:

?????? int pub;

?

protected:

?????? int pro;

?

private:

?????? int pri;

};

class Derived:public Base

{

public:

?????? Derived()

?????? { cout<<"Derived3()"<<endl; }

?????? Derived(int d1, int d2, int d3)

????????????? :Base(d1, d2, d3)

?????? {

????????????? d_pub = d1;

????????????? cout<<"Derived()"<<endl;

?????? }

?????? ~ Derived()

?????? { cout<<"~Derived()"<<endl; }

public:

?????? int d_pub;

protected:

?????? int d_pro;

private:

?????? int d_pri;

};

?

void FunTest()

{

?????? Base b0;

?????? Base b1(1, 2, 3);

?????? Base* pBase;

??????

?

?????? Derived d0;

?????? Derived d1(4, 5, 6);

?????? ?Derived* pDerived;

?

?????? b0 = d0;?//子類(lèi)對(duì)象可以賦值給父類(lèi)對(duì)象

?????? b1 = d1;

?

?????? d0 = bo; //? 父類(lèi)對(duì)象不能賦值給子類(lèi)對(duì)象

?????? d1 = b1;

?

?????? pBase = &d0;???? //父類(lèi)的指針/引用可以指向子類(lèi)對(duì)象

?????? pBase = &d1;

?

?????? Base& _b0 = d0;

?????? Base& _b1 = d1; //父類(lèi)的指針/引用可以指向子類(lèi)對(duì)象

?

?????? pDerived = &b0;

?????? Derived& = b1;//子類(lèi)的指針/引用不能指向父類(lèi)對(duì)象

?

?????? pDerived = (Derived *)&b1;?????? //可以使用的強(qiáng)制類(lèi)型轉(zhuǎn)換使子類(lèi)的指針/引用指向父類(lèi)對(duì)象

?

}

?

6、友元與繼承

友元關(guān)系不能繼承,也就是說(shuō)基類(lèi)友元不能訪(fǎng)問(wèn)子類(lèi)私有和保護(hù)成員。

class Base

{

public:

?????? Base()

?????? {

????????????? pub = 10;

????????????? pro = 10;

????????????? pri = 10;

????????????? ?cout<<"Base()"<<endl;

?????? }

?????? ~Base()

?????? {

????????????? cout<<"~Base()"<<endl;

?????? }

public:

?????? int pub;

protected:

?????? int pro;

private:

?????? int pri;

?friend void?????? show();

};

class Derived:public Base

{

public:

?????? Derived()

?????? {

????????????? d_pri= 10 ;

????????????? cout<<"Derived3()"<<endl;

?????? }

private:

?????? int d_pri;

};

void?????? show()

{

?????? Base b;

?????? cout<<b.pri<<endl; //友元函數(shù)可以訪(fǎng)問(wèn)基類(lèi)的私有成員

?????? Derived d;

?????? cout<<d.d_pri<<endl;?? //友元函數(shù)不能繼承,基類(lèi)的友元函數(shù)不可以訪(fǎng)問(wèn)子類(lèi)的私有成員

}

?

7、繼承的類(lèi)型

(1)單繼承:

class A

{

public:

?????? int data1;

} ;

class B? :public A

{

public:

?????? int data2;

} ;


(2)多繼承:

class A

{

public:

?????? int data1;

} ;

class B?

{

public:

?????? int data2;

}? ;

?class C :public A ,public B

{

public:

?????? int data3;

} ;

?

?

(3)???菱形繼承:

??????? class A

{

public:

?????? int data1;

} ;

class B: public A??????

{

public:

?????? int data2;

}? ;

?class C:public A

{

public:

?????? int data3;

} ;

class D:public B,public C

{

public:

?????? int data4;

} ;

?

?

?

?

?

D類(lèi)的對(duì)象中存在兩份A對(duì)象成員,菱形繼承存在二義性和數(shù)據(jù)冗余問(wèn)題

?

?

8、虛繼承--解決菱形繼承的二義性和數(shù)據(jù)冗余的問(wèn)題

?

?

?

class A

{

public:

??? int data1;

?

} ;

?

class B: virtual public A??

{

public:

??? int data2;

}? ;

?class C: virtual public A

{

public:

??? int data3;

} ;

?

?class D:public B,public C

{

public:

??? int data4;

} ;

?

?void FunTest()

?{

??? ?D d;

??? ?d.data1 = 1;

??? ?d.data2 = 2;

??? ?d.data3?= 3;

??? ?d.data4?= 4;

??? ?cout<<sizeof(B)<<endl;//12

??? ?cout<<sizeof(D)<<endl;//24

//0x0098F73C?000ecc88 00000002 000ecc94 00000003 00000004 00000001 ??? ?

?

?}


?



(1)虛繼承解決了在菱形繼承體系里面子類(lèi)對(duì)象包含多份父類(lèi)對(duì)象的數(shù)據(jù)冗余&浪費(fèi)空間的問(wèn)題。

(2)虛繼承體系看起來(lái)好復(fù)雜,在實(shí)際應(yīng)用我們通常不會(huì)定義如此復(fù)雜的繼承體系。一般不到萬(wàn)不得已都不要定義菱形結(jié)構(gòu)的虛繼承體系結(jié)構(gòu),

因?yàn)槭褂锰摾^承解決數(shù)據(jù)冗余問(wèn)題也帶來(lái)了性能上的損耗。



?就寫(xiě)到這了,有什么不對(duì)的大家指正哈!!!

?

?

?

總結(jié)

以上是生活随笔為你收集整理的C++ 继承解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。