组合类构造函数一般的定义形式如下:
类名::类名(形参表):内嵌对象1(形参表),内嵌对象2(形参表)...{
//初始化函数体
}
内嵌对象的初始化使用了 初始化列表 来完成——内嵌对象必须使用初始化列表来实现初始化。举个简单的例子——现在我们有一个圆的类Circle,以及一个点坐标的类 Point,定义如下:
class Point{
private:
int x,y;
public:
Point(int newX,int newY):x(newX),y(newY){}
};
class Circle{
private:
double radius;
point center;//圆的圆心点
public:
};
然后,对于circle类,它的构造函数就可以写成这个样子:
Circle(double r,point p):radius(r),center(p){
//构造函数初始化代码
}
当我们创建一个组合类的实例对象的时候,不光是它自己的构造函数的函数体被调用执行,而且还将调用其内嵌对象的构造函数。这个时候,构造函数的调用顺序如下所示:
析构函数的调用执行顺序与构造函数正好相反 ,析构函数的函数体被执行完毕之后,内嵌对象的析构函数开始被一一执行——它们的调用顺序,跟它们在组合类的定义中的顺序正好相反。需要注意的是,因为需要调用内嵌对象的析构函数——所以,虽然有的时候我们并没有显式定义析构函数,但是编译器自己生成的析构函数,也并不是跟以前一样“什么都不做”。 组合类的复制构造函数,默认状态下同样由编译器自行生成——它会自动调用各个内嵌对象的复制构造函数,为它们初始化。如果我们想要为组合类编写复制构造函数的话,那么我们需要为内嵌对象成员的复制构造函数传递参数。比如说,对于circle类,它的复制构造函数应该这样定义:
组合类的复制构造函数,默认状态下同样由编译器自行生成——它会自动调用各个内嵌对象的复制构造函数,为它们初始化。如果我们想要为组合类编写复制构造函数的话,那么我们需要为内嵌对象成员的复制构造函数传递参数。比如说,对于circle类,它的复制构造函数应该这样定义:
这里我们规定,Line类主要包括三个成员变量:两个Point类型成员p1,p2,分别表示线段的两个端点;double类型成员len,表示线段的长度。 Line类的默认构造函数需要两个Point类型的参数new_p1,new_p2.并且用初始化列表来为p1和p2进行初始化,最后写上空的大括号。 复制构造函数的定义——其参数类型为Line类型的对象l。别忘了这里要用引用传参哦!不然的话会造成额外的时间和空间开销。 添加一个getLen公有成员函数,作用是返回len的值
#include <iostream>
#include <cmath>
using std::cin;
using std::cout;
using std::endl;
class Point{
public:
Point(int newX = 0,int newY = 0){
x = newX;
y = newY;
}
Point(Point &p){
x = p.x;
y = p.y;
}
int getX() {
return x;
}
int getY() {
return y;
}
private:
int x,y;
};
class Line{
public:
Line(Point new_p1, Point new_p2):p1(new_p1),p2(new_p2){
double x = static_cast<double>(p1.getX() - p2.getX());
double y = static_cast<double>(p1.getY() - p2.getY());
len = sqrt(x*x + y*y);
}
Line(Line &l):p1(l.p1),p2(l.p2){
len = l.len;
}
double getLen(){
return len;
}
private:
Point p1, p2;
double len;
};
int main(){
Point pa(1,2);
Point pb(3,5);
Line L1(pa, pb);
Line L2(L1);
cout<<"The length of L1 is "<< L1.getLen()<<endl;
cout<<"The length of L2 is "<< L2.getLen()<<endl;
return 0;
}