亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

深入解析C++中派生類的構造函數

2020-05-23 14:14:06
字體:
來源:轉載
供稿:網友

這篇文章主要介紹了深入解析C++中派生類的構造函數,是C++入門學習中的基礎知識,需要的朋友可以參考下

基類的構造函數不能被繼承,在聲明派生類時,對繼承過來的成員變量的初始化工作也要由派生類的構造函數來完成。所以在設計派生類的構造函數時,不僅要考慮派生類新增的成員變量,還要考慮基類的成員變量,要讓它們都被初始化。

解決這個問題的思路是:在執行派生類的構造函數時,調用基類的構造函數。

下面的例子展示了如何在派生類的構造函數中調用基類的構造函數。

 

 
  1. #include<iostream> 
  2. using namespace std; 
  3. //基類 
  4. class People{ 
  5. protected
  6. char *name; 
  7. int age; 
  8. public
  9. People(char*, int); 
  10. }; 
  11. People::People(char *name, int age): name(name), age(age){} 
  12. //派生類 
  13. class Student: public People{ 
  14. private
  15. float score; 
  16. public
  17. Student(char*, intfloat); 
  18. void display(); 
  19. }; 
  20. //調用了基類的構造函數 
  21. Student::Student(char *name, int age, float score): People(name, age){ 
  22. this->score = score; 
  23. void Student::display(){ 
  24. cout<<name<<"的年齡是"<<age<<",成績是"<<score<<endl; 
  25. int main(){ 
  26. Student stu("小明", 16, 90.5); 
  27. stu.display(); 
  28. return 0; 

運行結果為:

小明的年齡是16,成績是90.5

請注意代碼第23行:

 

 
  1. Student::Student(char *name, int age, float score): People(name, age) 

這是派生類 Student 的構造函數的寫法。冒號前面是派生類構造函數的頭部,這和我們以前介紹的構造函數的形式一樣,但它的形參列表包括了初始化基類和派生類的成員變量所需的數據;冒號后面是對基類構造函數的調用,這和普通構造函數的參數初始化表非常類似。

實際上,你可以將對基類構造函數的調用和參數初始化表放在一起,如下所示:

 

 
  1. Student::Student(char *name, int age, float score): People(name, age), score(score){} 

基類構造函數和初始化表用逗號隔開。

需要注意的是:冒號后面是對基類構造函數的調用,而不是聲明,所以括號里的參數是實參,它們不但可以是派生類構造函數總參數表中的參數,還可以是局部變量、常量等。如下所示:

 

 
  1. Student::Student(char *name, int age, float score): People("李磊", 20) 

基類構造函數調用規則

事實上,通過派生類創建對象時必須要調用基類的構造函數,這是語法規定。也就是說,定義派生類構造函數時最好指明基類構造函數;如果不指明,就調用基類的默認構造函數(不帶參數的構造函數);如果沒有默認構造函數,那么編譯失敗。

請看下面的例子:

 

 
  1. #include<iostream> 
  2. using namespace std; 
  3. //基類 
  4. class People{ 
  5. protected
  6. char *name; 
  7. int age; 
  8. public
  9. People(); 
  10. People(char*, int); 
  11. }; 
  12. People::People(){ 
  13. this->name = "xxx"
  14. this->age = 0; 
  15. People::People(char *name, int age): name(name), age(age){} 
  16. //派生類 
  17. class Student: public People{ 
  18. private
  19. float score; 
  20. public
  21. Student(); 
  22. Student(char*, intfloat); 
  23. void display(); 
  24. }; 
  25. Student::Student(){ 
  26. this->score = 0.0; 
  27. Student::Student(char *name, int age, float score): People(name, age){ 
  28. this->score = score; 
  29. void Student::display(){ 
  30. cout<<name<<"的年齡是"<<age<<",成績是"<<score<<endl; 
  31. int main(){ 
  32. Student stu1; 
  33. stu1.display(); 
  34. Student stu2("小明", 16, 90.5); 
  35. stu2.display(); 
  36. return 0; 

運行結果:

 

 
  1. xxx的年齡是0,成績是0 
  2. 小明的年齡是16,成績是90.5 

創建對象 stu1 時,執行派生類的構造函數 Student::Student(),它并沒有指明要調用基類的哪一個構造函數,從運行結果可以很明顯地看出來,系統默認調用了不帶參數的構造函數,也就是 People::People()。

創建對象 stu2 時,執行派生類的構造函數 Student::Student(char *name, int age, float score),它指明了基類的構造函數。

在第31行代碼中,如果將 People(name, age) 去掉,也會調用默認構造函數,stu2.display() 的輸出結果將變為:

xxx的年齡是0,成績是90.5

如果將基類 People 中不帶參數的構造函數刪除,那么會發生編譯錯誤,因為創建對象 stu1 時沒有調用基類構造函數。

總結:如果基類有默認構造函數,那么在派生類構造函數中可以不指明,系統會默認調用;如果沒有,那么必須要指明,否則系統不知道如何調用基類的構造函數。

構造函數的調用順序

為了搞清這個問題,我們不妨先來看一個例子:

 

 
  1. #include<iostream> 
  2. using namespace std; 
  3. //基類 
  4. class People{ 
  5. protected
  6. char *name; 
  7. int age; 
  8. public
  9. People(); 
  10. People(char*, int); 
  11. }; 
  12. People::People(): name("xxx"), age(0){ 
  13. cout<<"PeoPle::People()"<<endl; 
  14. People::People(char *name, int age): name(name), age(age){ 
  15. cout<<"PeoPle::People(char *, int)"<<endl; 
  16. //派生類 
  17. class Student: public People{ 
  18. private
  19. float score; 
  20. public
  21. Student(); 
  22. Student(char*, intfloat); 
  23. }; 
  24. Student::Student(): score(0.0){ 
  25. cout<<"Student::Student()"<<endl; 
  26. Student::Student(char *name, int age, float score): People(name, age), score(score){ 
  27. cout<<"Student::Student(char*, int, float)"<<endl; 
  28. int main(){ 
  29. Student stu1; 
  30. cout<<"--------------------"<<endl; 
  31. Student stu2("小明", 16, 90.5); 
  32. return 0; 

運行結果:

 

 
  1. PeoPle::People() 
  2. Student::Student() 
  3. -------------------- 
  4. PeoPle::People(char *, int
  5. Student::Student(char*, intfloat

從運行結果可以清楚地看到,當創建派生類對象時,先調用基類構造函數,再調用派生類構造函數。如果繼承關系有好幾層的話,例如:

A --> B --> C

那么則創建C類對象時,構造函數的執行順序為:

A類構造函數 --> B類構造函數 --> C類構造函數

構造函數的調用順序是按照繼承的層次自頂向下、從基類再到派生類的。

C++有子對象的派生類的構造函數

類的數據成員不但可以是標準型(如int、char)或系統提供的類型(如string),還可以包含類對象,如可以在聲明一個類時包含這樣的數據成員:

 

 
  1. Student s1; //Student是已聲明的類名,s1是Student類的對象 

這時,s1就是類對象中的內嵌對象,稱為子對象(subobject),即對象中的對象。

那么,在對數據成員初始化時怎樣對子對象初始化呢?請仔細分析下面程序,特別注意派生類構造函數的寫法。

[例] 包含子對象的派生類的構造函數。為了簡化程序以易于閱讀,這里設基類Student的數據成員只有兩個,即num和name。

 

  1. #include <iostream> 
  2. #include <string> 
  3. using namespace std; 
  4. class Student//聲明基類 
  5. public//公用部分 
  6. Student(int n, string nam ) //基類構造函數,與例11.5相同 
  7. num=n; 
  8. name=nam; 
  9. void display( ) //成員函數,輸出基類數據成員 
  10. cout<<"num:"<<num<<endl<<"name:"<<name<<endl; 
  11. protected//保護部分 
  12. int num; 
  13. string name; 
  14. }; 
  15. class Student1: public Student //聲明公用派生類Student1 
  16. public
  17. Student1(int n, string nam,int n1, string nam1,int a, string ad):Student(n,nam),monitor(n1,nam1) //派生類構造函數 
  18. age=a; 
  19. addr=ad; 
  20. void show( ) 
  21. cout<<"This student is:"<<endl; 
  22. display(); //輸出num和name 
  23. cout<<"age: "<<age<<endl; //輸出age 
  24. cout<<"address: "<<addr<<endl<<endl; //輸出addr 
  25. void show_monitor( ) //成員函數,輸出子對象 
  26. cout<<endl<<"Class monitor is:"<<endl; 
  27. monitor.display( ); //調用基類成員函數 
  28. private//派生類的私有數據 
  29. Student monitor; //定義子對象(班長) 
  30. int age; 
  31. string addr; 
  32. }; 
  33. int main( ) 
  34. Student1 stud1(10010,"Wang-li",10001,"Li-sun",19,"115 Beijing Road,Shanghai"); 
  35. stud1.show( ); //輸出學生的數據 
  36. stud1.show_monitor(); //輸出子對象的數據 
  37. return 0; 

運行時的輸出如下:

 

 
  1. This student is: 
  2. num: 10010 
  3. name: Wang-li 
  4. age: 19 
  5. address:115 Beijing Road,Shanghai 
  6. Class monitor is: 
  7. num:10001 
  8. name:Li-sun 

請注意在派生類Student1中有一個數據成員:

 

 
  1. Student monitor; //定義子對象 monitor(班長) 

“班長”的類型不是簡單類型(如int、char、float等),它是Student類的對象。我們知道, 應當在建立對象時對它的數據成員初始化。那么怎樣對子對象初始化呢?顯然不能在聲明派生類時對它初始化(如Student monitor(10001, "Li-fun");),因為類是抽象類型,只是一個模型,是不能有具體的數據的,而且每一個派生類對象的子對象一般是不相同的(例如學生A、B、C的班長是A,而學生D、E、F的班長是F)。因此子對象的初始化是在建立派生類時通過調用派生類構造函數來實現的。

派生類構造函數的任務應該包括3個部分:

對基類數據成員初始化;

對子對象數據成員初始化;

對派生類數據成員初始化。

程序中派生類構造函數首部如下:

 

 
  1. Student1(int n, string nam,int n1, string nam1,int a, string ad): 
  2. Student(n,nam),monitor(n1,nam1) 

在上面的構造函數中有6個形參,前兩個作為基類構造函數的參數,第3、第4個作為子對象構造函數的參數,第5、第6個是用作派生類數據成員初始化的。

歸納起來,定義派生類構造函數的一般形式為: 派生類構造函數名(總參數表列): 基類構造函數名(參數表列), 子對象名(參數表列)

{

派生類中新增數成員據成員初始化語句

}

執行派生類構造函數的順序是:

調用基類構造函數,對基類數據成員初始化;

調用子對象構造函數,對子對象數據成員初始化;

再執行派生類構造函數本身,對派生類數據成員初始化。

派生類構造函數的總參數表列中的參數,應當包括基類構造函數和子對象的參數表列中的參數?;悩嬙旌瘮岛妥訉ο蟮拇涡蚩梢允侨我獾模缟厦娴呐缮悩嬙旌瘮凳撞靠梢詫懗?/p>

 

 
  1. Student1(int n, string nam,int n1, string nam1,int a, string ad): monitor(n1,nam1),Student(n,nam) 

編譯系統是根據相同的參數名(而不是根據參數的順序)來確立它們的傳遞關系的。但是習慣上一般先寫基類構造函數。

如果有多個子對象,派生類構造函數的寫法依此類推,應列出每一個子對象名及其參數表列。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91久久在线视频| 国产精品久久久久久久久久99| 国产69精品99久久久久久宅男| 成人看片人aa| 中文字幕欧美精品在线| 国产精品电影网| 久久久精品日本| 亚洲精品美女久久久| 黑人巨大精品欧美一区二区三区| 亚洲xxx大片| 在线成人激情黄色| 日韩高清免费在线| 成人国内精品久久久久一区| 国产精品免费一区二区三区都可以| 国产在线视频2019最新视频| 爽爽爽爽爽爽爽成人免费观看| 国产午夜精品视频免费不卡69堂| 日韩hd视频在线观看| 亚洲精品福利在线| 亚洲xxxx在线| 亚洲第一av网站| 国产一区二区香蕉| 午夜精品福利视频| 国产成人免费av| 亚洲mm色国产网站| 亚洲精品网址在线观看| 日本sm极度另类视频| 欧美性猛交视频| www.日韩av.com| 亚洲三级 欧美三级| 国内精品久久久久久中文字幕| 色狠狠av一区二区三区香蕉蜜桃| 国产欧美精品xxxx另类| 午夜精品美女自拍福到在线| 91久久久久久久久久久| 欧美国产日韩在线| 日韩男女性生活视频| 日韩有码在线播放| 国产成人av网| 亚洲娇小xxxx欧美娇小| 国产欧美日韩亚洲精品| 日韩在线视频网站| 精品香蕉一区二区三区| 一区二区在线视频| 国产欧美日韩精品在线观看| 国产精品观看在线亚洲人成网| 欧美精品videosex极品1| 国产视频一区在线| 欧美成人全部免费| 日韩av手机在线| 欧美性生活大片免费观看网址| 欧美大片在线影院| 色综合久久久888| 亚洲男人天堂手机在线| 国产精品扒开腿做爽爽爽的视频| 日韩精品极品视频| 91高潮精品免费porn| 视频在线观看一区二区| 国产精品视频久久| 久久久久久久91| 国产精品福利久久久| 最新91在线视频| 亚洲石原莉奈一区二区在线观看| 亚洲qvod图片区电影| 国产精品高清在线观看| 国产欧美日韩综合精品| 欧美性猛交xxxx乱大交蜜桃| 一本色道久久综合狠狠躁篇的优点| 成人黄在线观看| 这里只有精品久久| 高清欧美电影在线| 欧美激情xxxxx| 91在线高清视频| 欧美日韩中文字幕在线| 亚洲国产精品va在线| 色综合视频网站| 亚洲第一二三四五区| 国产精品视频成人| 欧美日韩第一视频| 亚洲第一福利视频| 黑人巨大精品欧美一区免费视频| 精品久久久999| 亚洲精品女av网站| 亚洲欧美日韩一区二区三区在线| 国产精品自产拍在线观| 亚洲国产成人精品久久久国产成人一区| 日韩经典中文字幕| 亚洲男人天堂2024| 国产日韩精品入口| 视频在线一区二区| 欧美另类99xxxxx| 亚洲欧美日本另类| 91国偷自产一区二区三区的观看方式| 亚洲网址你懂得| 精品一区二区三区四区| 国产在线拍揄自揄视频不卡99| 亚洲午夜精品久久久久久性色| 久久久久久久久久久av| 欧美一级片在线播放| 成人激情视频在线观看| 国产精品极品美女粉嫩高清在线| 亚洲一区二区三区乱码aⅴ蜜桃女| 久久国产精品影视| 黄色成人av在线| 亚洲精品久久久久久久久久久久久| 久久综合久久88| 国产午夜精品理论片a级探花| 国产69精品久久久久99| 欧美裸体xxxx极品少妇软件| 免费91麻豆精品国产自产在线观看| 国产精品成人免费视频| 日韩色av导航| 久久亚洲精品中文字幕冲田杏梨| 97成人精品区在线播放| 69视频在线播放| 欧美精品在线看| 精品国产精品三级精品av网址| 最新国产精品亚洲| www.欧美精品一二三区| 精品国产户外野外| 亚洲视频欧美视频| 欧美日韩亚洲激情| 91九色国产在线| 久久国产精品久久精品| 久久久国产精品免费| 欧美劲爆第一页| 欧美一区二粉嫩精品国产一线天| 国产成人精品在线播放| 亚洲欧美国产精品专区久久| 国产在线观看精品一区二区三区| 欧美一级大片在线免费观看| 中文字幕综合一区| 久久国产精品久久久久| 欧美激情一区二区三区久久久| 在线精品国产成人综合| 欧美日韩国产一区二区| 国产欧美一区二区三区久久人妖| 欧美黄色小视频| 欧美日韩在线免费观看| 久久精品这里热有精品| 久久久国产精品免费| 日本视频久久久| 91sao在线观看国产| 国产精品美女主播| 日韩经典中文字幕| 日韩精品在线播放| 久久国产精品首页| 亚洲人成电影在线| 丁香五六月婷婷久久激情| 亚洲精品免费网站| 欧洲成人免费aa| 亚洲精品不卡在线| 国产精品香蕉在线观看| 国产性色av一区二区| 另类天堂视频在线观看| 亚洲人成绝费网站色www| 亚洲成人中文字幕| 亚洲网站在线播放| zzijzzij亚洲日本成熟少妇| xxav国产精品美女主播| 欧美性生交大片免费| 一区二区三区四区视频| 亚洲精品一区二三区不卡| 亚洲一级黄色片|