假若计算机属于一个类,主板属于一个类,那个计算机类中就包含有主板类。
C++里一样,如果A类中有B类的成员,那么A就包含B
类的组合:一个类内嵌其它类的对象作为本身的成员。两者是包含与被包含的关系。
当创建类的对象时,如果这个类具有内嵌对象成员,那个各个内嵌对象应首先被自动创建。
在创建对象时既要对本类的基本类型数据成员进行初始化,同时又要对内嵌对象成员进行初始化。
组合类的构造函数定义:
类名::类名(形参表):内嵌对象1(形参表),内嵌对象2(形参表).......
{ 类 的初始化 }
详细为:
类名::类名(对象成员所需形参,本类成员形参):对象1(参数),对象2(参数),........
后面红色部分称为初始化列表,作用是对内嵌对象进行初始化。
对基本类型的数据成员也可以这样初始化,而且使用初始化列表比使用赋值语句的效率要高。
class Circle{
public:
Circle(float r);
float Circumference();
float Area();
private:
float radius;
}
上类的构造函数可这样写:
Circle::Circle(float r):radius(r){}
创建组合类的对象时,自身和内嵌的构造函数都将被调用,其顺序:
1、调用内嵌对象的构造函数,调用顺序按照内嵌对象在组合类的声明中出现的次序。
2、执行本类的构造函数。
如果组合类的对象没有指定对象的初始值,则默认形式(无形参)的构造函数将被调用。
析构函数的调用执行顺序与构造函数刚好相反。
--------------------------------------------
组合类同样有拷贝构造函数。若无则调用默认的拷贝构造函数。
组合类拷贝构造函数形式如下:
C::C(C & c1):b(c1,b) //假定C类包含B类对象b作为其成员
{ .......}
看一个例子。熟悉一下:
运行的结果如下:
分析主函数:第一句,point两个对象初始化,用了两次构造函数(非拷贝构造);
第二句,关键!!这是组合类的构造应这样进行:
首先:实参myp1和myp2对象要传递给构造函数中的形参xp1,xp2,这样就要进行两次point的拷贝构造函数;
然后:把此对象赋值给Line中的成员p1和p2,即:p1(xp1),p2(xp2) 这个形式多么熟悉,典型的拷贝构造函数形式,因此,
此时会再次调用两次拷贝构造函数。
在完成上面对内嵌对象构造后,才会执行构造函数内部,即构造本对象。
所以,就会有"LIne构造函数被调用"
第三句:本类的拷贝构造函数。同样应事先初始化内嵌对象p1(L.p1),p2(L.p2) 又是两次的point拷贝构造,这完成后,就是本类的拷贝构造完成。