公众号得到了大飞哥的支持,大佬还给出了课后思考题:为什么拷贝构造函数参数必须使用引用?
一开始我也没深究为什么,只是觉得语法规定这样就这样写。我们来看看不使用引用会怎样 ?
程序报错:Error1error C2652: 'Clock' : illegal copy constructor: first parameter must not be a 'Clock'
这里参数Clock T 对应前一篇文章三种情况中的情况二——对象以值传递的方式传入函数参数,会调用拷贝构造函数,形成无限递归,所以必须传引用。
想用机器人赋能未来,少不了扎实的编程基本功,继续跟着清华大学的C++ 程序设计学习吧~
在制造业中使用部件组装的方式生产效率更高,程序中也可以借用该思想。C++程序支持类的组合。
2 类的组合类中的数据成员是另一个类的对象。可以在已有抽象类的基础上实现更复杂的抽象。
类组合的构造函数的设计
原则:不仅要负责对本类中的基本类型成员数据初始化,也要对对象成员初始化。
声明形式:
类名::类名(对象成员所需的形参,本类成员形参): 对象1(参数),对象2(参数),...{//函数体其他语句}
构造组合类对象时的初始化次序
首先对构造函数初始化列表中列出的成员(包括基本类型成员和对象成员)进行初始化,初始化次序是成员在类体中定义的次序。
成员对象构造函数调用的顺序:按对象成员的定义顺序,先声明者先构造。
初始化列表中未出现的成员对象,调用默认构造函数(即无参的)初始化
处理完初始化列表之后,再执行构造函数的函数体。
组合类的例子
#includeusing namespace std;//Pointclass Point{private: double x,y;public: Point(double x,double y):x(x),y(y) { } Point(const Point &p)//Copy constructor { x=p.x; y=p.y; //cout< } double getX() { return x; } double getY() { return y; }};//Lineclass Line{public: Line(Point a,Point b):a(a),b(b) { double x=a.getX()-b.getX(); double y=a.getY()-b.getY(); length=sqrt(x*x+y*y); } Line(const Line & L):a(L.a),b(L.b){ length = L.length; }//组合类的拷贝构造 private: double length; Point a,b;};int main(){ Point a(1,2),b(3,4);//建立Point类的对象 Line ab(a,b);//建立Line类的对象 Line cd(ab);//用ab初始化cd system("Pause"); return 0;}
我们知道线段是由点组成的,因此当定义一个线段类需要包含点类的成员。
我们来单步调试下看看在建立组合类对象 Line ab(a,b); 时发生了什么。
首先进入到拷贝构造函数
先传的后一个参数b
再调用拷贝构造函数再传的前一个参数a
然后进入Line的构造函数
如何写组合类的拷贝构造函数呢,先按照以前的方式写下看看
Line(const Line & L){length = L.length; a = L.a; b = L.b; }
程序报错:
Point没有合适的默认构造函数,没有默认构造函数的内嵌对象Point初始化必须在构造函数的初始化列表中。
Line(const Line & L):a(L.a),b(L.b){ length = L.length; }
至此完成了组合类的拷贝构造。