1. 程式人生 > 實用技巧 >C++有子物件的派生類的建構函式

C++有子物件的派生類的建構函式

轉載:https://blog.csdn.net/qq1169091731/article/details/50934588?utm_source=blogxgwz6

類的資料成員不但可以是標準型(如int、char)或系統提供的型別(如string),還可以包含類物件,如可以在宣告一個類時包含這樣的資料成員:

class B{
…
};
class A{
public:
     B s1;  //B是已宣告的類名,s1是B類的物件
    …
 };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

這時,s1就是類物件中的內嵌物件,稱為子物件(subobject),即物件中的物件。
在派生類中,子物件為基類在派生類中定義的物件。如下列程式碼:

class Student{
…
};
class Student1:public Student{
private:
      Student a;              //這裡的a即為子物件
      …
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

通過例子來說明問題。在上篇部落格(C++派生類的建構函式)中的派生類Student1中,除了可以在派生類中要增加資料成員age和address外,還可以增加“班長”一項,即學生資料中包含他們的班長的姓名和其他基本情況,而班長本身也是學生,他也屬於Student型別,有學號和姓名等基本資料,這樣班長項就是派生類Student1中的子物件。在下面程式的派生類的資料成員中, 有一項monitor(班長),它是基類Student的物件,也就是派生類Student1的子物件。

那麼,在對資料成員初始化時怎樣對子物件初始化呢?請仔細分析下面程式,特別注意派生類建構函式的寫法。
[例11.6] 包含子物件的派生類的建構函式。為了簡化程式

以易於閱讀,這裡設基類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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

執行時的輸出如下:

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

請注意在派生類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個是用作派生類資料成員初始化的。

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

執行派生類建構函式的順序是:

呼叫基類建構函式,對基類資料成員初始化;
呼叫子物件建構函式,對子物件資料成員初始化;
再執行派生類建構函式本身,對派生類資料成員初始化。
  • 1
  • 2
  • 3

派生類建構函式的總引數表列中的引數,應當包括基類建構函式和子物件的引數表列中的引數。基類建構函式和子物件的次序可以是任意的,如上面的派生類建構函式首部可以寫成
Student1(int n, string nam,int n1, string nam1,int a, string ad): monitor(n1,nam1),Student(n,nam)
編譯系統是根據相同的引數名(而不是根據引數的順序)來確立它們的傳遞關係的。但是習慣上一般先寫基類建構函式。

如果有多個子物件,派生類建構函式的寫法依此類推,應列出每一個子物件名及其引數表列。