类的组合 构造函数的用法
在一个类中内嵌另一个类的对象作为数据成员,称为类的组合。该内嵌对象称为对象成员,或者子对象。如三角形类Triangle类的内嵌Node类作为数据成员;
class Triangle
{
private:
Node *nodei; //对象成员
Node *nodej;
Node *nodem;
public:
...
};
在使用过程中,需要着重注意的是 对象成员的初始化!如Triangle的构造函数该如何定义?
如果一个类具有内嵌对象,那么在它对象化的时候既要对基本数据成员初始化也要对内嵌的对象成员初始化。
class X
{
类名1 对象成员名1;
类名2 对象成员名2;
...
类名n 对象成员名n;
};
一般来说类X的构造函数定义形式为:
X::X(形参表0):对象成员名1(形参1),...,对象成员名n(形参n)
{
类X的构造函数体
}
形参1到n一般来自形参表0;而且当调用构造函数的时候,首先按照在类的声明中的顺序依次调用对象成员函数的构造函数,对这些对象初始化,最后执行够赞函数体初始化类中的其他数据成员;析构函数的调用顺序与构造函数相反!举例说明:
#include<iostream>
using namespace std;
class Node
{
private:
double x_;
double y_;
public:
Node(double x=0,double y=0) //带默认参数的构造函数
{
x_=x;
y_=y;
cout<<"x="<<x_<<endl;
}
~Node() //Node类的析构函数
{
cout<<"x="<<x_<<endl;
}
};
class Triangle
{
private:
Node nodei;
Node nodej;
Node nodem;
public:
Triangle(double a1,double b1,double a2,double b2,double a3,double b3):nodei(a1,b1),
nodej(a2,b2),nodem(a3,b3)//内嵌对象成员的Triangle类的构造函数定义
{}
~Triangle() //Triangle类析构函数
{}
};
int main()
{
Triangle tri(1,1,2,2,3,3); //初始化
return 0;
}
输出结果:
说明:如果类的内嵌对象是用指针表示的,如何初始化呢?这个时候用上述的初始化列表就失效了!
#include<iostream>
using namespace std;
class Node
{
private:
double x_;
double y_;
public:
Node(double x=0,double y=0) //带默认参数的构造函数
{
x_=x;
y_=y;
cout<<"x="<<x_<<endl;
}
void init(double x,double y)//自定义初始化函数
{
x_=x;
y_=y;
}
~Node() //Node类的析构函数
{
cout<<"x="<<x_<<endl;
}
void disp(void) //输出函数
{
cout<<"x="<<x_<<endl;
}
};
class Triangle
{
private:
Node *nodei; //数据成员为指向Node类型的指针
Node *nodej;
Node *nodem;
public:
Triangle(double a1,double b1,double a2,double b2,double a3,double b3)
{
Node *node1,*node2,*node3;
//定义参量指针
node1=new Node; //动态分配内存
node2=new Node;
node3=new Node;
node1->init(a1,b1); //调用自定义init()初始化三个点
node2->init(a2,b2);
node3->init(a3,b3);
nodei=node1; //再将初始化也即分配了内存后的指针值赋给数据成员
nodej=node2;
nodem=node3;
nodei->disp(); //打印赋值结果
nodej->disp();
nodem->disp();
//delete node3; //释放指针所指
//delete node2;
//delete node1;
}
~Triangle() //Triangle类析构函数
{
}
void disp()
{
nodei->disp();
nodej->disp();
nodem->disp();
}
};
int main()
{
Triangle tri(1,1,2,2,3,3); //初始化
tri.disp();
return 0;
}
输出结果为:
显然这样定义构造函数既不直观(不知道那个参数对应那个点)也很麻烦!改为如下:
#include<iostream>
using namespace std;
class Node
{
private:
double x_;
double y_;
public:
Node(double x=0,double y=0) //带默认参数的构造函数
{
x_=x;
y_=y;
cout<<"x="<<x_<<endl;
}
void init(double x,double y)//自定义初始化函数
{
x_=x;
y_=y;
}
~Node() //Node类的析构函数
{
cout<<"x="<<x_<<endl;
}
void disp(void) //输出函数
{
cout<<"x="<<x_<<endl;
}
};
class Triangle
{
private:
Node *nodei; //数据成员为指向Node类型的指针
Node *nodej;
Node *nodem;
public:
Triangle(Node& node1,Node& node2,Node& node3)
{
//nodei=new Node; //动态分配内存
//nodej=new Node;
//nodem=new Node;
nodei=&node1; //地址传递
nodej=&node2;
nodem=&node3;
nodei->disp(); //打印赋值结果
nodej->disp();
nodem->disp();
//delete node3; //释放指针所指
//delete node2;
//delete node1;
}
~Triangle() //Triangle类析构函数
{
}
void disp()
{
nodei->disp();
nodej->disp();
nodem->disp();
}
};
int main()
{
Node nod1(1,1),nod2(2,2),nod3(3,3);
Triangle tri(nod1,nod2,nod3); //初始化
//tri.disp();
return 0;
}
输出:
这样来定义构造函数既没有用到init()自定义的初始化函数,而且物理意义明确。
总结:1.有子对象的类的初始化问题。子对象不是直接用类名表示,可以用初始化列表初始化。
2.如果子对象用指针形式表示,就不能用初始化列表了。