類的組合(C++學習筆記 29)
計算機硬體可構成計算機硬體類。計算機硬體類的資料成員有型號、CPU引數、記憶體引數、硬碟引數、廠家等。其中的資料成員“ 廠家 ”又是計算機公司類的物件。這樣,計算機硬體類的資料成員中就可以有計算機公司類的物件,或者反過來說,計算機公司類的物件又是計算機硬體類的一個數據成員。這樣,當生成一個計算機硬體類物件時,其中就巢狀著一個計算機公司類物件。
類的組合: 在一個類中內嵌另一個類的物件作為資料成員。該內嵌物件稱為物件成員,也稱為子物件。例如:
class A{
//···
};
class B{
A a; //類 A 的物件 a 為類 B 的物件成員
public :
//······
};
當建立類的物件時(如建立類 B 的物件),如果這個類具有內嵌的物件成員(如內嵌的物件成員 a),那麼物件成員也將被自動建立。因此,在建立物件時,既要對本類的基本資料成員初始化,又要對內嵌的物件成員進行初始化。含有物件成員的類,其建構函式和不含物件成員的建構函式有所不同。例如有以下的類 X:
class X{
類名1 物件成員1;
類名2 物件成員2;
···
類名3 物件成員n;
};
一般來說,類 X 的建構函式的定義形式為:
X::X(形參表0):物件成員1(形參表1),物件成員2(形參表2),···
{
//類 X 的建構函式體
}
其中,“ 物件成員1(形參表1),物件成員2(形參表2),··· ” 稱作初始化表,其作用是對物件成員進行初始化。
當呼叫建構函式 X::X( )時,首先按個內嵌物件成員在類宣告中的順序依次呼叫它們的建構函式,對這些物件初始化,最後再執行類 X 的建構函式體,初始化類 X 中的其他成員,解構函式的呼叫順序與建構函式的呼叫順序相反。
例 1:物件成員的初始化。
#include<iostream>
using namespace std;
class A{
public:
A(int x1,float y1){
x=x1;
y=y1;
}
void show(){
cout<<"\n x="<<x<<" y="<<y;
}
private:
int x;
float y;
};
class B{
public:
B(int x1,float y1,int z1):a(x1,y1){
z=z1;
}
void show(){
a.show();
cout<<" z="<<z;
}
private:
A a; //類 A 的物件 a 為類 B 的物件成員
int z;
};
int main(){
B b(11,22,33);
b.show();
return 0;
}
例 2:物件成員的應用。
每個學生的學習成績應該含有多門課的成績。考慮到所有學習成績的性質和處理都是一致的,所以學習成績也可以單獨作為一個類(成績類),而把類 Student 中的成員 score 作為成績類的一個物件。這樣,一個學生類中就巢狀著一個成績類物件。
#include<iostream>
#include<string.h>
using namespace std;
class Score{
public:
Score(float c=0,float e=0,float m=0);
void show();
private:
float computer;
float english;
float mathematics;
};
Score::Score(float c,float e,float m){
computer=c;
english=e;
mathematics=m;
}
void Score::show(){
cout<<"\n 計算機成績:"<<computer;
cout<<"\n 英語成績:"<<english;
cout<<"\n 數學成績:"<<mathematics;
}
class Student{
private:
char *name;
char *stu_no;
Score score1; //物件成員,是類Score的物件
public:
Student(char *name1,char *stu_no1,float s1,float s2,float s3):score1(s1,s2,s3){ //建構函式
name=new char[strlen(name1)+1];
strcpy(name,name1);
stu_no=new char[strlen(stu_no1)];
strcpy(stu_no,stu_no1);
}
~Student(){
delete []name;
delete []stu_no;
}
void show(){
cout<<"\n 姓名:"<<name;
cout<<"\n 學號:"<<stu_no;
score1.show();
}
};
int main(){
Student stu1("哈利波特","01",90,88,90);
stu1.show();
cout<<endl;
Student stu2("羅恩","02",88,88,90);
stu2.show();
cout<<endl;
Student stu3("赫敏","03",99,97,99);
stu3.show();
cout<<endl;
}
執行結果:
使用String類來使該程式簡潔一點,把Student類改一下:
class Student{
private:
string name;
string stu_no;
Score score1; //物件成員,是類Score的物件
public:
Student(string name1,string stu_no1,float s1,float s2,float s3):score1(s1,s2,s3){ //建構函式
name=name1;
stu_no=stu_no1;
}
void show(){
cout<<"\n 姓名:"<<name;
cout<<"\n 學號:"<<stu_no;
score1.show();
}
};
說明:
(1)宣告一個含有物件的類,首先要建立物件成員。如本例在宣告類 Student 中,定義了物件成員 score1:Score score1;
。
(2)在定義類 Student 的物件,呼叫建構函式進行初始化的同時,也要對物件成員進行初始化,因為它也是屬於此類的成員。因此在寫類 Student 的建構函式時,也綴上了物件成員 score1 要呼叫的類 Score 的建構函式:
Student(char *name1,char *stu_no1,float s1,float s2,float s3):score1(s1,s2,s3){
//建構函式
}
這時建構函式的呼叫順序是:先呼叫物件成員 score1 的建構函式,對物件成員的資料成員進行初始化。隨後再執行類 Student 建構函式的函式體,對派生類資料成員進行初始化。
注意:在定義類 Student 的建構函式時,必須綴上物件成員的名字 score1,而不能綴上類名,若寫成:
Student(char *name1,char *stu_no1,float s1,float s2,float s3):Score(s1,s2,s3){
//建構函式
}
是不允許的,因為在類 Student 中是類 Score 的物件 score1 作為成員,而不是類 Score 作為其成員。