C++:类的组合
在类中定义的数据成员一般都是基本数据类型或服复合数据类型。但是还可以根据需要使用
其他类的对象作为正在声明的数据成员。复杂的对象还可以有比较简单的对象一某种方式组合
而成,复杂对象和组成它的简单对象之间的关系是组合关系。
在一个类中内嵌另一个类的对象作为数据成员,称为类的组合。该内嵌对象称为对象成员,也称为
子对象。例如:
class A
{
.......
};
class B
{
A a; //类A的对象a为类B的对象成员
public:
....
};
当创建类的对象时,如果这个类具有内嵌对象成员,那么内嵌对象成员也将被自动创建,因此,
在创建对象时既要对本类的基本数据成员初始化,又要对内嵌的对象成员进行初始化。含有对象
成员的类,其构造函数和不含对象成员的构造函数有所不同,例如有以下的类X:
class X{
类名1 对象成员 1;
类名2 对象成员 2;
.................
类名n 对象成员 n;
};
一般来说,类X的构造函数的定义形式为:
X::X(形参表0):对象成员1(形参表1),对象成员2(形参表2),对象成员3(形参表3),....
{
//类的构造函数体
}
其中,"对象成员1(形参表1),对象成员2(形参表2),对象成员3(形参表3),...."称作初始化表,其作用
是对对象成员进行初始化。
当调用构造函数X::X()时,首先按各内嵌对象成员在类声明中的顺序依次调用他们的构造函数,对这些
对象初始化。最后在执行类X的构造函数体,初始化类X的其他成员。析构函数的调用顺序与构造函数的
调用顺序相反。
例: 对象成员的初始化
#include<iostream> using namespace std; class A{ //声明类A public: A(int x1,float y1) { x = x1; y = y1; } void show() { cout<<"x="<<x<<endl; cout<<"y="<<y<<endl; } private: int x; float y; }; class B{ //声明类B public: B(int x1,float y1,int z1):a(x1,y1) //类B的构造函数,含有初始化列表,用与对内嵌对象a进行初始化 { z = z1; } void show() { a.show(); cout<<"z="<<z<<endl; } private: A a; //类A的对象a为类B的对象成员 int z; }; int main() { B b(11,22,33); b.show(); return 0; }
需求:定义学生类和成绩类,将student类的成员score作为成绩类的一个对象 ,然后用初始化
列表进行初始化。
例 :对象成员的应用
#include<iostream> #include<string> using namespace std; class Score{ //声明类Score public: Score(float m,float l,float E); void show(); private: float math; float language; float English; }; Score::Score(float m,float l,float E) //定义构造函数 { math = m; language = l; English = E; } void Score::show() { cout<<"数学的成绩是:"<<math<<endl; cout<<"语文的成绩是:"<<language<<endl; cout<<"英语的成绩是:"<<English<<endl; } class Student{ //声明类student public: Student(char* n,char* s,float m,float l,float E); //声明构造函数 ~Student(); //声明析构函数 void show(); private: char* name; //学生姓名 char* sno; //学生学号 Score Sco; //对象成员,是类Score的对象 }; Student::Student(char* n,char* s,float m,float l,float E):Sco(m,l,E) //定义构造函数 { name = new char[strlen(n)+1]; strcpy(name,n); sno = new char[strlen(n)+1]; strcpy(sno,s); } Student::~Student() { delete []name; delete []sno; } void Student::show() { cout<<"学生的姓名是:"<<name<<endl; cout<<"学生的学号是:"<<sno<<endl; Sco.show(); } int main() { Student stu1("张三","1011",98.3,98.6,99.1); //定义类student的对象stu1,调用stu1的构造函数, //初始化对象stu1 stu1.show(); //调用stu1的show(),显示stu1的数据 cout<<endl; Student stu2("李四","1012",98.8,98.5,99.5); stu2.show(); cout<<endl; }
从上面的程序可以看出,类student的show函数中对于对象成员Sco的处理方式就是通过调用类Score的show函数
来实现的。
说明:
1、声明含有对象的类,首先要创建对象成员。本例在声明类Studet中,定义了对象成员Sco;
Score Sco;
2、在定义类Student的对象,调用构造函数进行初始化的同时,也要对对象成员进行初始化,因为它
属于此类的成员。因此在写类Student的构造函数时,也缀上了对象成员Sco要调用类Score的构造
函数。
Student::Student(char* n,char* s,float m,float l,float E):Sco(m,l,E){}
这时构造函数的调用顺序是:先调用对象成员Sco的构造函数,对对象成员的数据成员进行初始化。
随后再执行类Student的构造函数的函数体,对派生类数据成员进行初始化。
注意:在定义类Student的构造函数时,必须缀上对象成员的名字Sco,而不能缀上类名。。。