自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

適合具備 C 語(yǔ)言基礎(chǔ)的 C++ 教程之五

開發(fā) 后端
在本節(jié)我們將依次闡述封裝、繼承、派生的具體用法,在這里,我們先敘述的是封裝這個(gè)屬性的的相關(guān)內(nèi)容。下圖是關(guān)于 封裝 這個(gè)特性所包含的一些內(nèi)容。

[[382696]]

前言

在上述教程中,我們已經(jīng)完成了 C++相對(duì)于 C語(yǔ)言來(lái)說(shuō)獨(dú)特的語(yǔ)法部分,在接下來(lái)的教程中,我們將敘述 C++中面向?qū)ο蟮恼Z(yǔ)法特性。我們?cè)趯W(xué)習(xí)面向?qū)ο蟮倪@種編程方法的時(shí)候,常常會(huì)聽到這三個(gè)詞,封裝、繼承、派生,這也是面向?qū)ο缶幊痰娜筇匦?,在本?jié)我們將依次闡述封裝、繼承、派生的具體用法,在這里,我們先敘述的是封裝這個(gè)屬性的的相關(guān)內(nèi)容。下圖是關(guān)于 封裝 這個(gè)特性所包含的一些內(nèi)容。

封裝

下圖就是封裝所具備的相關(guān)特性:

image-20210209204824118 

那么上圖所示的抽象出數(shù)據(jù)成員以及成員函數(shù)具體的含義是什么呢,正如前面教程所述,在前面的教程里,我們選用一個(gè) Person類來(lái)作為例子進(jìn)行講解,其中這個(gè)類里我們有 name以及age,這個(gè)也就是我們抽象出來(lái)的數(shù)據(jù),那抽象出來(lái)的成員函數(shù)也就是前面教程講到的setName()和setAge()函數(shù),在設(shè)計(jì)這個(gè)類的時(shí)候,會(huì)把這個(gè)類的一些成員設(shè)置為私有的或者公有的,這也就是訪問(wèn)控制。具體的代碼如下所示:

  1. /* 為了代碼簡(jiǎn)便,省略相關(guān)構(gòu)造函數(shù)以及析構(gòu)函數(shù),為的是展示封裝的特性*/ 
  2. class Person { 
  3. private: 
  4.     char *name
  5.     int age; 
  6.  
  7. public
  8.  
  9.     Person() 
  10.     { 
  11.         cout << "Person" << endl; 
  12.         name = NULL
  13.     } 
  14.  
  15.     ~Person() 
  16.     { 
  17.         cout << "~Person()" << endl; 
  18.         if (this->name
  19.         { 
  20.             delete this->name
  21.         } 
  22.     } 
  23.  
  24.     void setName(char *name
  25.     { 
  26.         if (this->name) { 
  27.             delete this->name
  28.         } 
  29.         this->name = new char[strlen(name) + 1]; 
  30.         strcpy(this->namename); 
  31.     } 
  32.  
  33.     int setAge(int a) 
  34.     { 
  35.         if (a < 0 || a > 150) 
  36.         { 
  37.             age = 0; 
  38.             return -1; 
  39.         } 
  40.         age = a; 
  41.         return 0; 
  42.     } 
  43. }; 

繼承

繼承的含義就如其字面意思一樣,用更加專業(yè)的話來(lái)說(shuō),就是從基類繼承相關(guān)屬性,而這個(gè)新的類就叫做派生類。下面這個(gè)示意圖也表明了繼承所帶來(lái)的代碼的簡(jiǎn)潔與方便。

image-20210209211013964 

就如上述這張圖所示,一個(gè)人肯定具有名字和年齡這兩個(gè)屬性,那作為一個(gè)學(xué)生來(lái)講,他也必定具備名字和年齡這兩個(gè)屬性,那這個(gè)時(shí)候是要在 Student類里重新定義這些屬性么?顯然,因?yàn)橐肓死^承這個(gè)特性,只需要繼承Person類,那么Student就具備 Person類的相關(guān)屬性。在上述代碼的基礎(chǔ)上,我們?cè)黾尤缦滤镜拇a:

  1. /* 注意是在上述代碼的基礎(chǔ)上 */ 
  2.  
  3. class Student : public Person 
  4.  
  5. }; 
  6.  
  7. int main(int argc, char **argv) 
  8.     Student s; 
  9.  
  10.     s.setName("zhangsan"); 
  11.     s.setAge(16); 
  12.     s.printInfo(); 
  13.  
  14.     return 0; 

上述代碼中,Student類是繼承自 Person類的,我們可以看到在上述所示的Student類中,并沒有setName和 setAge的成員函數(shù),但是在定義的 Student實(shí)例中,卻能夠適用 setName和 setAge的成員函數(shù),這也就說(shuō)明了 Student類已經(jīng)繼承了 Person類。

繼承后的訪問(wèn)控制

private

一個(gè)派生類從一個(gè)基類繼承而來(lái),而繼承的方式有多種,可以是私有繼承,也可以是公有繼承,同時(shí)也可以是保護(hù)繼承。那么這個(gè)時(shí)候基類的各個(gè)數(shù)據(jù)成員的訪問(wèn)屬性又是怎么樣的呢,我們來(lái)看一下下面這張圖,其展現(xiàn)了以各種方式繼承自基類的派生類的數(shù)據(jù)成員的屬性。

image-20210209223145289 

從這個(gè)表可以清楚地知道基類的訪問(wèn)屬性與派生類的訪問(wèn)屬性的對(duì)應(yīng)情況。同樣的,我們用一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明這個(gè)知識(shí)點(diǎn):

  1. class Father 
  2. private: 
  3.     int money; 
  4. public
  5.     void it_skill(void) 
  6.     { 
  7.         cout << "The father's it skill" <<endl; 
  8.     } 
  9.  
  10.     int getMoney(void) 
  11.     { 
  12.         return money; 
  13.     } 
  14.  
  15.     void setMoney(int money) 
  16.     { 
  17.         this->money = money; 
  18.     } 
  19. }; 

這個(gè)是基類的數(shù)據(jù)成員以及成員函數(shù),為了更好的說(shuō)明繼承后的數(shù)據(jù)的屬性,我們定義一個(gè) son類,代碼如下所示:

  1. class Son : public Father 
  2. private: 
  3.     int toy; 
  4. public
  5.     void play_game(void) 
  6.     { 
  7.         cout << "play_game()" << endl; 
  8.  
  9.         int m; 
  10.  
  11.         //money -= 1; /* 錯(cuò)誤的代碼 */ 
  12.  
  13.         m = getMoney(); 
  14.         m--; 
  15.         setMoney(m); 
  16.     } 
  17. }; 

上述定義了兩個(gè)類,一個(gè)是 Father類,一個(gè)是 Son類,Son類繼承于 Father類,這兩個(gè)類用通俗的語(yǔ)言進(jìn)行解釋便是,父親有自己的私房錢,兒子有自己的玩具,父親有一項(xiàng)技能是 it,兒子呢比較喜歡玩游戲。因?yàn)槭抢^承,所以兒子類具有父親類的相關(guān)屬性,但是,作為兒子是不能夠直接去父親兜里拿錢的,那會(huì)被揍,但是如果兒子需要錢,可以向父親要。這對(duì)應(yīng)的代碼也就是上述中 money -= 1,但是這是錯(cuò)誤的,不能直接從父親的兜里拿錢,而剩余的三句代碼的意思也就相當(dāng)于是向父親要錢。用專業(yè)的話來(lái)講也就是:派生類不能夠訪問(wèn)基類的私有成員,緊接著是主函數(shù)的代碼:

  1. int main(int argc, char **argv) 
  2.     Son s; 
  3.  
  4.     s.it_skill(); 
  5.     s.setMoney(10); 
  6.     cout << "The money is:" << s.getMoney() << endl; 
  7.  
  8.     s.play_game(); 
  9.  
  10.     return 0; 

代碼輸出的結(jié)果如下所示:

image-20210209232507917 

protected

還是采用比較通俗的話來(lái)敘述這一知識(shí)點(diǎn),兒子相對(duì)于父親的關(guān)系自然是與其他人有所不同的,比如有一把父親房間門的鑰匙,對(duì)于兒子來(lái)說(shuō)是可以拿到的,但是對(duì)于外人來(lái)說(shuō),這是不可訪問(wèn)的。那在程序中要如何實(shí)現(xiàn)這么一個(gè)功能呢?這里就要引入 protected了。代碼如下所示:

  1. class Father { 
  2. private: 
  3.     int money; 
  4.  
  5. protected: 
  6.     int room_key;   /* 增添的 room_key */ 
  7.  
  8. public
  9.     void it_skill(void) 
  10.     { 
  11.         cout<<"father's it skill"<<endl; 
  12.     } 
  13.  
  14.     int getMoney(void) 
  15.     { 
  16.         return money; 
  17.     } 
  18.  
  19.     void setMoney(int money) 
  20.     { 
  21.         this->money = money; 
  22.     } 
  23. }; 

我們可以看到在 Father類中,增添了一項(xiàng)就是 protected修飾的 room_key,緊接著我們來(lái)看Son類的代碼:

  1. class Son : public Father { 
  2. private: 
  3.     int toy; 
  4. public
  5.     void play_game(void) 
  6.     { 
  7.         int m; 
  8.  
  9.         cout<<"son paly game"<<endl; 
  10.  
  11.         m = getMoney(); 
  12.         m--; 
  13.         setMoney(m); 
  14.  
  15.         /* 外人不能拿父親的房間鑰匙 
  16.          * 兒子可以 
  17.          */ 
  18.         room_key = 1;  
  19.     } 
  20. }; 

我們看到,這個(gè)時(shí)候,是可以在 Son類里面直接操作使用 protected修飾的 room_key的。在這里總結(jié)一下就是:派生類可以直接訪問(wèn)到基類用 protected 修飾的數(shù)據(jù)成員。接下來(lái),我們繼續(xù)看主函數(shù)的代碼:

  1. int main(int argc, char **argv) 
  2.     Son s; 
  3.  
  4.     s.setMoney(10); 
  5.     cout << s.getMoney()<<endl; 
  6.  
  7.     s.it_skill(); 
  8.     s.play_game();   
  9.  
  10.     //s.room_key = 1; 
  11.  
  12.     return 0; 

通過(guò)上述代碼可以看到 s.room_key = 1這條語(yǔ)句被注釋了,這條語(yǔ)句是錯(cuò)誤的,雖然基類使用了 protected修飾了 room_key,但是在主函數(shù)中,仍然是不能夠直接訪問(wèn) room_key的。

調(diào)整訪問(wèn)控制

依舊采用比較通俗的話來(lái)闡述,如果兒子從父親那里繼承了一些東西,那這個(gè)時(shí)候,繼承得到的這些東西的處理權(quán)就全在兒子了。在程序里面也是同樣的道理,我們?cè)谏鲜龃a的基礎(chǔ)上進(jìn)行更改,F(xiàn)ather類不變,改變 Son類。代碼如下所示:

  1. class Son : public Father { 
  2. private: 
  3.     int toy; 
  4. public
  5.     using Father::room_key; 
  6.  
  7.     void play_game(void) 
  8.     { 
  9.         int m; 
  10.  
  11.         cout<<"son paly game"<<endl; 
  12.  
  13.         m = getMoney(); 
  14.         m--; 
  15.         setMoney(m); 
  16.  
  17.         room_key = 1;  
  18.     } 
  19. }; 

上述代碼中,我們可以看到在 public的作用域內(nèi),我們使用 using Father::room_key將 room_key的屬性更改為 public,做了這樣的更改之后,我們就可以在主函數(shù)里直接訪問(wèn) room_key了。代碼如下所示:

  1. int main(int argc, char **argv) 
  2.     Son s; 
  3.  
  4.     s.setMoney(10); 
  5.     cout << s.getMoney()<<endl; 
  6.  
  7.     s.it_skill(); 
  8.     s.play_game(); 
  9.  
  10.     s.room_key = 1; 
  11.  
  12.     return 0; 

上述代碼是可以運(yùn)行的,也說(shuō)明這種方式是可行的。但是如果想要將 money的屬性更改為 public,也就是增加如下所示的代碼:

  1. class Son : public Father { 
  2. private: 
  3.     int toy; 
  4. public
  5.     using Father::room_key; 
  6.     using Father::money; 
  7.  
  8.     void play_game(void) 
  9.     { 
  10.         int m; 
  11.  
  12.         cout<<"son paly game"<<endl; 
  13.  
  14.         m = getMoney(); 
  15.         m--; 
  16.         setMoney(m); 
  17.  
  18.         room_key = 1;  
  19.     } 
  20. }; 

那么編譯將不會(huì)通過(guò),錯(cuò)誤信息如下所示:

image-20210210001456319 

說(shuō)明這種方法是不可行的,這是為什么呢?是因?yàn)閷?duì)于 Son來(lái)說(shuō),money本身就是它不能訪問(wèn)到的數(shù)據(jù),那么自然也就不能夠?qū)ζ鋵傩赃M(jìn)行更改了。換句更加專業(yè)的話來(lái)敘述也就是:在調(diào)整訪問(wèn)控制的時(shí)候,只有類本身能夠訪問(wèn)到的數(shù)據(jù)才能調(diào)整它的訪問(wèn)控制,如果其本身對(duì)于這個(gè)類就是不能夠訪問(wèn)的,那么也就無(wú)法對(duì)其進(jìn)行更改。

那上述可以說(shuō)是提升訪問(wèn)控制,同樣的,也可以降低訪問(wèn)控制,比如說(shuō)上述的 it_skill,如果不想把這個(gè)屬性繼續(xù)繼承下去或者說(shuō)不讓外部能夠訪問(wèn)到它,那么也可以降低它的訪問(wèn)控制,降低的方法跟提升的方法是一樣的,只需要在 private中加上一句代碼就可以,加了的代碼如下所示:

  1. class Son : public Father 
  2. private: 
  3.     int toy; 
  4.     using Father::it_skill; 
  5. public
  6.     /* 省略 */ 
  7. }; 

因此,只要對(duì)于派生類能夠看到的數(shù)據(jù)成員或者成員函數(shù),它都能夠提高或者降低它的訪問(wèn)控制。

三種不同繼承方式的差異

在上述的內(nèi)容中,我們提到了派生類在繼承基類的時(shí)候,存在不同的繼承方式,不同的繼承方式對(duì)數(shù)據(jù)成員的使用以及其成員函數(shù)的調(diào)用存在不同的影響,下面分別是三種不同的繼承方式:public和 private以及protected,代碼如下所示:

  1. /* 以 public 方式繼承 */ 
  2. class Son_pub : public Father { 
  3. private: 
  4.     int toy; 
  5. public
  6.  
  7.     void play_game(void) 
  8.     { 
  9.         int m; 
  10.  
  11.         cout<<"son play game"<<endl; 
  12.  
  13.         m = getMoney(); 
  14.         m--; 
  15.         setMoney(m); 
  16.  
  17.         room_key = 1;  
  18.     } 
  19. }; 
  20.  
  21. /* 以 private 方式繼承 */ 
  22. class Son_pri : private Father { 
  23. private: 
  24.     int toy; 
  25. public
  26.  
  27.     void play_game(void) 
  28.     { 
  29.         int m; 
  30.  
  31.         cout<<"son play game"<<endl; 
  32.         m = getMoney(); 
  33.         m--; 
  34.         setMoney(m); 
  35.  
  36.         room_key = 1;  
  37.     } 
  38. }; 
  39.  
  40. /* 以 protected 方式繼承 */ 
  41. class Son_pro : protected Father { 
  42. private: 
  43.     int toy; 
  44. public
  45.  
  46.     void play_game(void) 
  47.     { 
  48.         int m; 
  49.  
  50.         cout<<"son play game"<<endl; 
  51.         m = getMoney(); 
  52.         m--; 
  53.         setMoney(m); 
  54.  
  55.         room_key = 1;  
  56.     } 
  57. }; 

上述代碼就是以三種不同方式從 Father類得到的 Son類,每一種繼承方式存在什么不同呢,我們通過(guò)主函數(shù)來(lái)說(shuō)明這個(gè)問(wèn)題:

  1. int main(int argc, char **argv) 
  2.     Son_pub s_pub; 
  3.     Son_pro s_pro; 
  4.     Son_pri s_pri; 
  5.  
  6.     s_pub.play_game(); 
  7.     s_pro.play_game(); 
  8.     s_pri.play_game(); 
  9.  
  10.     s_pub.it_skill(); 
  11.     //s_pro.it_skill();  // error 
  12.     //s_pri.it_skill();  // error 
  13.  
  14.     return 0; 

通過(guò)上述代碼,并對(duì)照上述那種表,我們可以知道,無(wú)論是何種繼承方式,派生類內(nèi)部public的成員函數(shù)都是可以使用的,而對(duì)于從基類繼承得到的成員函數(shù),如果是以 protected和private方式來(lái)繼承的話,那么是不能夠在主函數(shù)進(jìn)行調(diào)用的,因此上述代碼中注釋掉的兩句后面表明了錯(cuò)誤。

上述的代碼所展示的是一層的繼承,我們?cè)诶^承得到的派生類 Son的基礎(chǔ)上繼續(xù)繼承得到 Grandson,首先我們先在 Father類里新增加一個(gè)public的數(shù)據(jù)成員,增加的代碼如下所示:

  1. class Father 
  2. private: 
  3.     int money; 
  4. protected: 
  5.     int room_key; 
  6. public
  7.     int address; 
  8.     /*其余不改動(dòng),省略*/ 
  9. }; 

增加了上述Father類的代碼之后,我們來(lái)看 Grandson_pub類的代碼:

  1. class Grandson_pub : public Son_pub 
  2. public
  3.     void test(void) 
  4.     { 
  5.         room_key = 1; /* room_key is protected */ 
  6.         address = 2;  /* address is public */ 
  7.     } 
  8. }; 

上述代碼中,Grandson_pub是以 public的方式從 Son_pub繼承而來(lái),room_key在 Father類是 protected,在 Son_pub類也是 protected,那么在這里也是 protected,而對(duì)于 address來(lái)說(shuō),它在 Father類里是 public,在 Son_pub里也是 public,在這里也是 public,所以在這里都能夠訪問(wèn)到。

緊接著來(lái)看,Grandson_pro類的代碼:

  1. class Grandson_pro : public Son_pro 
  2. public
  3.     void test(void) 
  4.     { 
  5.         room_key = 1;  /* room_key is protected */ 
  6.         address = 2;   /* address is protected */ 
  7.     } 
  8. }; 

上述中,Grandson_pro是以 public的方式從 Son_pro中繼承得到的,以剛剛那種分析的思路我們能夠分析得出 room_key當(dāng)前是 protected以及 address是 protected,那么當(dāng)前的數(shù)據(jù)成員在這也就是都能夠訪問(wèn)的了。

繼續(xù)來(lái)看Grandson_pri類的代碼,代碼如下所示:

  1. class Grandson_pri : public Son_pri 
  2. public
  3.     void test(void) 
  4.     { 
  5.         //room_key = 1; /* room_key is private */ 
  6.         //address = 2;  /* address is private */ 
  7.     } 
  8. }; 

上述中,Grandson_pri是以 public的方式從 Son_pri中繼承得來(lái),同樣按照上述的分析方法,我們能夠分析出 room_key和 address都是 private的,既然是 private的,那么也就不能夠進(jìn)行訪問(wèn),因此上述代碼中,我們將兩句代碼進(jìn)行了注釋。

小結(jié)

上述就是本次分享的關(guān)于封裝以及繼承的相關(guān)內(nèi)容,主要是關(guān)于繼承之后數(shù)據(jù)成員的訪問(wèn)控制,以及通過(guò)不同的方式進(jìn)行繼承時(shí)的數(shù)據(jù)成員的訪問(wèn)控制。

上述教程所涉及的代碼可以通過(guò)百度云鏈接的方式獲取到,下面是百度云鏈接:

鏈接:https://pan.baidu.com/s/18AGYqxkxsEcR4ZW6_Nhevg

提取碼:dlst

本文轉(zhuǎn)載自微信公眾號(hào)「 wenzi嵌入式軟件」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系 wenzi嵌入式軟件公眾號(hào)。

 

 

責(zé)任編輯:武曉燕 來(lái)源: wenzi嵌入式軟件
相關(guān)推薦

2021-02-20 06:13:18

C 語(yǔ)言C++

2021-02-11 08:25:17

C 語(yǔ)言C++ 基礎(chǔ)

2021-02-16 10:57:34

C++ C 語(yǔ)言windows

2021-02-08 20:25:12

C 語(yǔ)言C++Linux

2021-07-16 07:21:45

C++可調(diào)用對(duì)象std::functi

2021-04-25 08:11:57

C語(yǔ)言常量與變量標(biāo)識(shí)符命名規(guī)范

2010-01-15 17:38:37

C++語(yǔ)言

2010-01-19 14:45:35

C++語(yǔ)言

2020-08-21 13:20:36

C++If ElseLinux

2011-07-14 17:45:06

CC++

2021-02-06 07:49:48

C語(yǔ)言編程開發(fā)技術(shù)

2011-07-15 00:47:13

C++多態(tài)

2011-01-05 11:12:34

C++

2022-01-14 09:10:56

C++文件Linux

2020-07-30 12:40:35

CC++編程語(yǔ)言

2011-07-13 18:24:18

C++

2022-07-01 11:56:54

C語(yǔ)言C++編程語(yǔ)言

2010-01-22 15:30:36

C++語(yǔ)言

2024-02-21 14:55:19

C++語(yǔ)言編程

2010-01-14 10:34:02

C++語(yǔ)言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)