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

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

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

2020-01-26 14:51:27
字體:
來源:轉載
供稿:網友

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

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

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

#include<iostream>using namespace std;//基類class People{protected:  char *name;  int age;public:  People(char*, int);};People::People(char *name, int age): name(name), age(age){}//派生類class Student: public People{private:  float score;public:  Student(char*, int, float);  void display();};//調用了基類的構造函數Student::Student(char *name, int age, float score): People(name, age){  this->score = score;}void Student::display(){  cout<<name<<"的年齡是"<<age<<",成績是"<<score<<endl;}int main(){  Student stu("小明", 16, 90.5);  stu.display();  return 0;}

運行結果為:
小明的年齡是16,成績是90.5

請注意代碼第23行:

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


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

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

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


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

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

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


基類構造函數調用規則

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

請看下面的例子:

#include<iostream>using namespace std;//基類class People{protected:  char *name;  int age;public:  People();  People(char*, int);};People::People(){  this->name = "xxx";  this->age = 0;}People::People(char *name, int age): name(name), age(age){}//派生類class Student: public People{private:  float score;public:  Student();  Student(char*, int, float);  void display();};Student::Student(){  this->score = 0.0;}Student::Student(char *name, int age, float score): People(name, age){  this->score = score;}void Student::display(){  cout<<name<<"的年齡是"<<age<<",成績是"<<score<<endl;}int main(){  Student stu1;  stu1.display();  Student stu2("小明", 16, 90.5);  stu2.display();  return 0;}

運行結果:

xxx的年齡是0,成績是0小明的年齡是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 時沒有調用基類構造函數。

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

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

#include<iostream>using namespace std;//基類class People{protected:  char *name;  int age;public:  People();  People(char*, int);};People::People(): name("xxx"), age(0){  cout<<"PeoPle::People()"<<endl;}People::People(char *name, int age): name(name), age(age){  cout<<"PeoPle::People(char *, int)"<<endl;}//派生類class Student: public People{private:  float score;public:  Student();  Student(char*, int, float);};Student::Student(): score(0.0){  cout<<"Student::Student()"<<endl;}Student::Student(char *name, int age, float score): People(name, age), score(score){  cout<<"Student::Student(char*, int, float)"<<endl;}int main(){  Student stu1;  cout<<"--------------------"<<endl;  Student stu2("小明", 16, 90.5);  return 0;}

運行結果:

PeoPle::People()Student::Student()--------------------PeoPle::People(char *, int)Student::Student(char*, int, float)

從運行結果可以清楚地看到,當創建派生類對象時,先調用基類構造函數,再調用派生類構造函數。如果繼承關系有好幾層的話,例如:
A --> B --> C
那么則創建C類對象時,構造函數的執行順序為:
A類構造函數 --> B類構造函數 --> C類構造函數
構造函數的調用順序是按照繼承的層次自頂向下、從基類再到派生類的。

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

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


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


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

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

#include <iostream>#include <string>using namespace std;class Student//聲明基類{public: //公用部分  Student(int n, string nam ) //基類構造函數,與例11.5相同  {   num=n;   name=nam;  }  void display( ) //成員函數,輸出基類數據成員  {   cout<<"num:"<<num<<endl<<"name:"<<name<<endl;  }protected: //保護部分  int num;  string name;};class Student1: public Student //聲明公用派生類Student1{public:  Student1(int n, string nam,int n1, string nam1,int a, string ad):Student(n,nam),monitor(n1,nam1) //派生類構造函數  {   age=a;   addr=ad;  }  void show( )  {   cout<<"This student is:"<<endl;   display(); //輸出num和name   cout<<"age: "<<age<<endl; //輸出age   cout<<"address: "<<addr<<endl<<endl; //輸出addr  }  void show_monitor( ) //成員函數,輸出子對象  {   cout<<endl<<"Class monitor is:"<<endl;   monitor.display( ); //調用基類成員函數  }private: //派生類的私有數據  Student monitor; //定義子對象(班長)  int age;  string addr;};int main( ){  Student1 stud1(10010,"Wang-li",10001,"Li-sun",19,"115 Beijing Road,Shanghai");  stud1.show( ); //輸出學生的數據  stud1.show_monitor(); //輸出子對象的數據  return 0;}

運行時的輸出如下:

This student is:num: 10010name: Wang-liage: 19address:115 Beijing Road,ShanghaiClass monitor is:num:10001name:Li-sun

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

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

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

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

  1. 對基類數據成員初始化;
  2. 對子對象數據成員初始化;
  3. 對派生類數據成員初始化。

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

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


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

歸納起來,定義派生類構造函數的一般形式為: 派生類構造函數名(總參數表列): 基類構造函數名(參數表列), 子對象名(參數表列)
{
派生類中新增數成員據成員初始化語句
}

執行派生類構造函數的順序是:
調用基類構造函數,對基類數據成員初始化;
調用子對象構造函數,對子對象數據成員初始化;
再執行派生類構造函數本身,對派生類數據成員初始化。

派生類構造函數的總參數表列中的參數,應當包括基類構造函數和子對象的參數表列中的參數。基類構造函數和子對象的次序可以是任意的,如上面的派生類構造函數首部可以寫成

  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精品国产91久久久久久久久| 国产欧美日韩精品专区| 国产精品毛片a∨一区二区三区|国| 中文字幕在线看视频国产欧美在线看完整| 91av视频在线免费观看| 亚洲精品美女网站| 91精品国产自产在线观看永久| 欧美成人免费视频| 欧美精品在线播放| 欧美国产在线视频| 在线成人中文字幕| 日韩欧美一区视频| 日韩中文在线视频| 久久在线免费视频| 国产精品欧美在线| 欧美乱大交xxxxx| 亚洲三级 欧美三级| 亚洲精品永久免费精品| www高清在线视频日韩欧美| 国产精品久久久久久av福利| 欧美电影在线观看网站| 亚洲精品福利资源站| 中文字幕日韩欧美在线视频| 亚洲一级一级97网| 国产精品久久久久久久7电影| 亚洲视频电影图片偷拍一区| 亚洲欧美日韩天堂| 欧美孕妇孕交黑巨大网站| 永久免费看mv网站入口亚洲| 国产精品综合久久久| 91中文字幕一区| 亚洲欧美日韩国产中文专区| 亚洲免费一在线| 最近2019免费中文字幕视频三| 国产欧美va欧美va香蕉在| 欧美大奶子在线| 97视频免费看| 国产视频久久久久久久| 久久久精品一区二区| 色99之美女主播在线视频| 亚洲男人的天堂在线播放| 久久久久久久影视| 91国内免费在线视频| 欧洲亚洲免费在线| 欧美在线亚洲在线| 亚洲国产日韩精品在线| 亚洲无限乱码一二三四麻| 欧美激情精品久久久久| 欧美日韩精品在线视频| 国产区亚洲区欧美区| 欧美激情日韩图片| 亚洲国产精品久久久久秋霞蜜臀| 日韩欧美精品免费在线| 亚洲国产精品高清久久久| 欧亚精品中文字幕| 国产精品自拍小视频| 久久久久久国产精品久久| 亚洲久久久久久久久久久| 亚洲成人激情小说| 色999日韩欧美国产| 亚洲福利视频二区| 久久久99久久精品女同性| 九色精品免费永久在线| 亚洲国产成人精品电影| 日韩免费高清在线观看| 欧美成人精品三级在线观看| 菠萝蜜影院一区二区免费| 欧美一级大胆视频| 国产成人黄色av| 中国人与牲禽动交精品| 国产精品久久久久久五月尺| 欧美一级免费看| 色综合久久悠悠| 日韩激情在线视频| 久久精品在线播放| 久久人人爽人人| 国产a级全部精品| 久久成人精品一区二区三区| 国产成人一区二区在线| 亚洲一区二区三区xxx视频| 精品国模在线视频| 亚洲一区二区三区视频播放| 免费不卡在线观看av| 亚洲国产古装精品网站| 亚洲国产欧美自拍| 国产丝袜精品第一页| 69国产精品成人在线播放| 日韩av大片在线| 精品美女国产在线| 欧美极度另类性三渗透| 日本精品久久久久影院| 日韩视频免费在线| 国产精品第3页| 久久中文字幕视频| 欧美高清视频在线播放| 亚洲午夜国产成人av电影男同| 黄色成人av在线| 久久av.com| 国产精品露脸av在线| 亚洲国产精品网站| 久久精品国产91精品亚洲| 福利精品视频在线| 欧美亚洲在线播放| 成人精品一区二区三区电影免费| 日韩美女av在线| 在线播放精品一区二区三区| 日本欧美在线视频| 欧美高清在线观看| 俺去了亚洲欧美日韩| 亚洲自拍欧美色图| 91免费看国产| 国产成人一区二| 97欧美精品一区二区三区| 亚洲剧情一区二区| 精品久久香蕉国产线看观看亚洲| 亚洲一区亚洲二区| 日韩专区中文字幕| 成人综合国产精品| 欧美性猛交xxxx偷拍洗澡| 日韩av成人在线观看| 日韩电影大片中文字幕| 国模精品视频一区二区三区| 欧美性资源免费| 国产精品视频一区国模私拍| 亚洲欧美中文日韩在线v日本| 中文字幕亚洲欧美日韩2019| …久久精品99久久香蕉国产| 成人a在线视频| 国产一区二区黄| 国产精品入口免费视频一| 亚洲伊人久久综合| 成人午夜在线影院| 亚洲精品国产品国语在线| 91综合免费在线| 欧美午夜视频在线观看| 国产精品视频xxx| 日本国产一区二区三区| 日韩久久免费电影| 日韩欧美在线视频免费观看| 国产精品久久久久久婷婷天堂| 91免费福利视频| 91午夜理伦私人影院| 精品国产91乱高清在线观看| 亚洲国产精品久久精品怡红院| 国产成人精品免费久久久久| 自拍偷拍亚洲精品| 高清一区二区三区四区五区| 成人国产精品久久久久久亚洲| 色偷偷偷亚洲综合网另类| 日韩午夜在线视频| 国产午夜精品视频| 国产精品69久久久久| 一区二区三区国产视频| 日韩视频免费看| 国产精品久久婷婷六月丁香| 欧美电影在线观看高清| 久久免费福利视频| 欧美午夜精品久久久久久久| 欧美午夜电影在线| 欧美在线精品免播放器视频| 98精品国产高清在线xxxx天堂| 亚洲激情在线观看| 久久久国产精品x99av| 国模极品一区二区三区|