在学习C++的类时,碰到了构造函数,而关于构造函数又引申出了复杂情况下构造函数的调用顺序。看视频讲解、敲示例代码,算是大概清楚了调用次序,为了今后查询,特意在此记录一下。
- 构造函数:创建类对象时,初始化对象
- 复制构造函数:用已经存在的类对象,初始化一个新创建的同类型的类对象
复制构造函数调用的情况有三种:
1、用已存在的类对象,去初始化一个新创建的类对象
2、类对象作为函数的实参
3、类对象作为函数的返回值
- 组合类的构造函数:类的成员是另一个类的对象
当上述三个在一起出现时,各自的调用顺序是如何。也就是什么时候调用构造函数,什么时候调用复制构造函数,什么时候调用组合类的构造函数,而什么时候又调用组合类的复制构造函数??
以下的程序可以解释在上述都存在的情况下,调用次序。
#include <iostream>
using namespace std;
//点类
class Point {
public:
Point(int newX, int newY);//自定义构造函数
Point();//默认构造函数
Point(const Point& p);//复制构造函数
int getX() {
return x;
}
int getY() {
return y;
}
private:
int x;
int y;
};
//自定义构造函数实现
Point::Point(int newX, int newY) :x(newX), y(newY) {
cout << "Calling constructor of Point." << endl;
}
//默认构造函数实现
Point::Point() :x(0), y(0) {}
//复制构造函数实现
Point::Point(const Point& p) {
x = p.x;
y = p.y;
cout << "Calling copy constructor of Point." << endl;
}
//线类
class Line {
public:
Line(Point xp1, Point xp2);//组合类构造函数
Line(Line& l);//组合类的复制构造函数
double getLen() { return len; }
private:
Point p1, p2;
double len;
};
//组合类构造函数的具体实现
Line::Line(Point xp1, Point xp2) :p1(xp1), p2(xp2) {
cout << "Calling constructor of Line." << endl;
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(Line& l) :p1(l.p1), p2(l.p2) {
cout << "Calling the copy constructot of Line." << endl;
len = l.len;
}
int main() {
Point myp1(1, 1), myp2(5, 5);//建立point类的对象
Line myL1(myp1, myp2);//利用已存在的point对象,去建立line类的对象
Line myL2(myL1);//利用line的复制构造函数建立一个新的对象
cout << "The length of myL1 is:" << myL1.getLen() << endl;
cout << "The length of myL2 is:" << myL2.getLen() << endl;
return 0;
}
1、创建Point类对象myp1和myp2时,调用Point类的构造函数
2、利用已经存在的Point类对象构建并初始化Line类对象,而这其中:
根据vs情况下的调试跟踪,向myL1传参时的顺序是先传入myp2,再传入myp1。
创建对象myL1时,需要调用Line类的构造函数,由构造函数的形参是对象,首先需要形实结合,才能进入函数主体。
在形实结合时,结合复制构造函数的调用情况,可知会调用两次Point类的复制构造函数。
然后进行初始化,又结合复制构造函数的调用情况,可知会调用两次Point类的复制构造函数。
之后,进入Line构造函数主体。
3、创建Line类对象myL2时,考虑到是类初始化类,因此需要调用Line类的复制构造函数。而在此之前,涉及到形参初始化,需要先调用两次Point类的复制构造函数。
至此,整个调用顺序大致流程如上。
附上vs调试的结果图