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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

初识C++之继承

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

1、何為繼承

  C++中所謂繼承,就是在一個(gè)已存在類的基礎(chǔ)上創(chuàng)建一個(gè)新的類,新類獲得已存在類的部分特性(為什么是部分特性,后面會(huì)講到)。已存在類被稱為基類(Base Class)或父類(Father Class),新建類被稱為派生類(Derived Class)或子類(Son Class)。

繼承的聲明形式:
class 派生類名:[繼承方式] 基類列表
{
  派生類增加的特性;
}

2、分類

繼承在C++中有單繼承與多繼承的分類。
單繼承:派生類有且只有一個(gè)基類
多繼承:派生類兩個(gè)或兩個(gè)以上的基類
文字描述不過癮,給出聲明方法、模型及實(shí)例:
①簡(jiǎn)單的單繼承聲明方法、模型及實(shí)例:

class 派生類名:[繼承方式] 基類名
{
  派生類增加的特性;
}

class Base //父類/基類 {void Fun(){cout << "Base" << endl;} protected:int data; };class Derived1: public Base //子類1/派生類1 {void Fun(){cout << "Derived1" << endl;} private:int _data; };class Derived2: public Base //子類2/派生類2 {void Fun(){cout << "Derived2" << endl;} private:int _data; };

②簡(jiǎn)單的多繼承聲明方法、模型及實(shí)例:

class 派生類名:[繼承方式] 基類列表
{
  派生類增加的特性;
}

class Base1 {void Fun(){cout << "Base" << endl;} protected:int data1; };class Base2 {void Fun(){cout << "Base" << endl;} protected:int data2; };class Derived: public Base1, public Base2 {void Fun(){cout << "Derived" << endl;} private:int _data; };

3、繼承方式

先來回憶一下繼承的聲明形式:
class 派生類名:[繼承方式] 基類列表
{
  派生類增加的特性;
}
  其中,繼承方式分為共有(public)、私有(private)、保護(hù)(protected)之分,不同的繼承方式會(huì)產(chǎn)生不同的繼承效果(class默認(rèn)繼承方式是私有,struct默認(rèn)繼承方式是公有,但最好還是顯示給出繼承方式,這樣會(huì)使程序更加清晰)。
  
繼承方式的區(qū)別:
public:基類的非私有成員在派生類中的訪問屬性不變,基類的私有屬性在派生類中存在但不可見。
protected:基類的非私有成員都稱為派生類中的保護(hù)成員,基類的私有屬性在派生類中存在但不可見。
private:基類的非私有成員都稱為派生類中的私有成員,基類的私有屬性在派生類中存在但不可見。
以上就是為什么說只是基類的部分特性在派生類中可見。

#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std;class Base { public:Base(){}~Base(){}void ShowBase(){cout << "ShowBase" << endl;cout << "pri = " << pri << endl;cout << "pro = " << pro << endl;cout << "pub = " << pub << endl;}private:int pri; protected:int pro; public:int pub; };class Derived :public Base { public:Derived(){}~Derived(){}void ShowDerived(){cout << "ShowDerived" << endl;cout << "_pri = " << _pri << endl;cout << "_pro = " << _pro << endl;cout << "_pub = " << _pub << endl;}private:int _pri; protected:int _pro; public:int _pub; };int main() {Base b;Derived d;b.ShowBase();d.ShowBase(); d.ShowDerived();cout << sizeof(Base) << endl;cout << sizeof(Derived) << endl;return 0; }

輸出結(jié)果:

對(duì)以上輸出結(jié)果分析:
①為什么ShowBase會(huì)被調(diào)用兩次
  ShowBase函數(shù)被調(diào)用了兩次,是因?yàn)樵贒erived類中,繼承有ShowBase函數(shù),因?yàn)樵摵瘮?shù)在Base類中的屬性是public,而且Derived類是以public方式繼承自Base類的,所以該函數(shù)在Derived類中的屬性仍為public,那么它就可以在類外被調(diào)用。
②為什么兩個(gè)類的大小不同
  從輸出結(jié)果中很明顯的看到,Base類的大小為12,Derived類的大小為2。Base類的大小為12很好理解,因?yàn)樗锩嬷挥腥齻€(gè)成員變量,且都為int類型,但為什么Derived是24呢,這就要牽扯到了繼承方式特性,不管繼承方式是什么,基類的成員變量的訪問限定符是什么,基類的成員變量在派生類中都是存在的,只是有可見與不可見之分。
當(dāng)我把繼承方式修改為protected和private時(shí),程序編譯出錯(cuò):


這就印證了我們上述的繼承方式的特性,因?yàn)閜rotected繼承方式會(huì)把Base類中public訪問限定符的BaseShow函數(shù)在Derived類中降級(jí)為protected訪問限定符,同樣,private繼承方式會(huì)把Base類中public訪問限定符的BaseShow函數(shù)在Derived類中降級(jí)為private訪問限定符,而protected訪問限定符和private訪問限定符修飾的內(nèi)容在類外是不可見的,強(qiáng)行調(diào)用肯定會(huì)報(bào)錯(cuò),所以這兒會(huì)出現(xiàn)錯(cuò)誤。

繼承方式的特性:
①基類的private成員在派生類中是不能被訪問的,如果基類成員不想在類外直接被訪問,但需要在派生類中能訪問,就定義為protected。可以看出保護(hù)成員限定符是因繼承才出現(xiàn)的。
②不管是哪種繼承方式,在派生類內(nèi)部都可以訪問基類的公有成員和保護(hù)成員,基類的私有成員存在但是在子類中不可見(不能訪問)。
③使用關(guān)鍵字class時(shí)默認(rèn)的繼承方式是private,使用struct時(shí)默認(rèn)的繼承方式是public,不過最好顯示的寫出繼承方式。

4、繼承關(guān)系中構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用
先給出一個(gè)例子來剖析:

#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std;class Base { public:Base(){cout << "Base()" << endl;}~Base(){cout << "~Base()" << endl;}private:int pri; protected:int pro; public:int pub; };class Derived :protected Base { public:Derived(){cout << "Derived()" << endl;}~Derived(){cout << "~Derived()" << endl;}private:int _pri; protected:int _pro; public:int _pub; };int main() {Base b;Derived d;return 0; }

可以看到在派生類創(chuàng)建對(duì)象時(shí),是先調(diào)用基類的構(gòu)造函數(shù),然后在代用自己的構(gòu)造函數(shù),對(duì)于析構(gòu)函數(shù)就很好解釋了,可以理解為棧的特性,先進(jìn)后出。

5、繼承關(guān)系的作用域
在C++的繼承體系中,基類和派生類是屬于兩個(gè)不同作用域。當(dāng)基類和派生類中有同名成員時(shí),派生類成員將屏蔽基類對(duì)成員的直接訪問(在派生類成員函數(shù)中,可以使用 基類名::基類成員來訪問基類的同名成員),這就是所謂的同名隱藏,在派生類中的同名成員稱為對(duì)基類同名成員的重定義。當(dāng)然,實(shí)際中在繼承體系里面最好不要定義同名的成員。
注意:因?yàn)榛惡团缮愂菍儆趦蓚€(gè)不同作用域,所以兩個(gè)類中的同名函數(shù)不會(huì)構(gòu)成函數(shù)重載。

#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std;class Base { public:Base(int _pub = 0, int _pri = 1, int _pro = 2): pub(_pub), pri(_pri), pro(_pro){}~Base(){}void Display(){cout << "Base::Display" << endl;cout << "pub = " << pub << endl;cout << "pri = " << pri << endl;cout << "pro = " << pro << endl;} public:int pub; private:int pri; protected:int pro; };class Derived: public Base { public:Derived(int _pub = 0, int _pri = 1, int _pro = 2): pub(_pub), pri(_pri), pro(_pro){}~Derived(){}void Display(){cout << "Derived::Display" << endl;cout << "pub = " << pub << endl;cout << "pri = " << pri << endl;cout << "pro = " << pro << endl;} public:int pub; private:int pri; protected:int pro; };int main() {Base b(1, 2, 3);Derived d(4, 5, 6);b.Display();d.Display();return 0; }

根據(jù)上面例子的輸出就可以看出來。

6、基類對(duì)象與派生類對(duì)象的賦值關(guān)系

①子類對(duì)象可以賦值給父類對(duì)象

#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std;class Base { public:Base(int bpub = 5, int bpri = 10, int bpro = 15): pub(bpub), pri(bpri), pro(bpro){}~Base(){}void Display(){cout << "Base::Display" << endl;cout << "pub = " << pub << endl;cout << "pri = " << pri << endl;cout << "pro = " << pro << endl;}public:int pub; private:int pri; protected:int pro; };class Derived: public Base { public:Derived(int _dpub = 10, int _dpri = 20, int _dpro = 30): _pub(_dpub), _pri(_dpri), _pro(_dpro){}~Derived(){}void Display(){cout << "Derived::Display" << endl;cout << "_pub = " << _pub << endl;cout << "_pri = " << _pri << endl;cout << "_pro = " << _pro << endl;}public:int _pub; private:int _pri; protected:int _pro; };int main() {Base b(1, 2, 3);Derived d(4, 5, 6);b = d;b.Display();d.Display();return 0; }

輸出結(jié)果:

程序可以正常輸出,但有些人可能會(huì)奇怪,為什么b里面存的是5、10、15,而不是4、5、6,其實(shí)原因很簡(jiǎn)單:

②父類對(duì)象不能賦值給子類對(duì)象
當(dāng)我把上例中的“b = d;”換成“d = b;”時(shí),編譯器會(huì)報(bào)錯(cuò):

還是像剛才那樣分析:

③父類的指針/引用可以指向子類對(duì)象,但是無法使用不存在于基類只存在于派生類的元素。

#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std;class Base { public:Base(int bpub = 5, int bpri = 10, int bpro = 15): pub(bpub), pri(bpri), pro(bpro){}~Base(){}void Display(){cout << "Base::Display" << endl;cout << "pub = " << pub << endl;cout << "pri = " << pri << endl;cout << "pro = " << pro << endl;}public:int pub; private:int pri; protected:int pro; };class Derived: public Base { public:Derived(int _dpub = 10, int _dpri = 20, int _dpro = 30): _pub(_dpub), _pri(_dpri), _pro(_dpro){}~Derived(){}void Display(){cout << "Derived::Display" << endl;cout << "_pub = " << _pub << endl;cout << "_pri = " << _pri << endl;cout << "_pro = " << _pro << endl;}public:int _pub; private:int _pri; protected:int _pro; };int main() {Derived d(4, 5, 6);Base *b = &d;b->Display();return 0; }

輸出結(jié)果:

上分析圖:

④子類的指針/引用不能指向父類對(duì)象(可以通過強(qiáng)制類型轉(zhuǎn)換完成)
我把上例中的

int main() {Derived d(4, 5, 6);Base *b = &d;b->Display();return 0; }

換成

int main() {Base b(4, 5, 6);Derived *d = &b;d->Display();return 0; }

程序會(huì)報(bào)錯(cuò):

繼續(xù)上圖分析:

7、友元與繼承
友元關(guān)系不能繼承,也就是說基類友元不能訪問子類私有和保護(hù)成員。

8、繼承與靜態(tài)成員
基類定義了static成員,則整個(gè)繼承體系里面只有一個(gè)這樣的成員。無論派生出多少個(gè)子類,都只有一個(gè)static成員實(shí)例。

#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std;class Base { public:Base(int bpub = 5, int bsta = 0, int bpri = 10, int bpro = 15): pub(bpub), pri(bpri), pro(bpro){}~Base(){}void Display(){cout << "Base::Display" << endl;cout << "sta = " << sta << endl;}public:int pub;static int sta; private:int pri; protected:int pro; };class Derived: public Base { public:Derived(int _dpub = 10, int _dpri = 20, int _dpro = 30): _pub(_dpub), _pri(_dpri), _pro(_dpro){}~Derived(){}void Display(){cout << "Derived::Display" << endl;cout << "sta = " << sta << endl;}public:int _pub; private:int _pri; protected:int _pro; };int Base::sta = 10;int main() {Base b;Derived d;b.Display();d.Display();return 0; }

可以看到兩次輸出都是10。

總結(jié)

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

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