"组合"通常在希望新类有老类功能的时候使用,但是又不希望使用老类的接口。
举个简单的例子:
#include <iostream>
using namespace std;class P {
public:
void My_Special_talent()
{
//......
}};
class Company {
private:
P p;
public:
void Conpany_Special_talent()
{
p.My_Special_talent();
}
};int main()
{
Company c;
c.Conpany_Special_talent();
return 0;
}这里的P类就好比是你,你拥有着自己独特的一门技术 My_Special_talent(),然后毕业了你找到了一份满意的工作。
而类Company就是你将要上班工作的公司,紧接着进入公司后你的技术被公司吸收了:
你的技术很好,大家都知道能够它能够高效地解决这一类的问题,所以以后公司一旦有这一类的问题,就直接交给你了,但也没人问你是怎么完成的,只要你完成就好了。
(这个时候类P的接口已经被重新封装了(本来属于你的技能,现在已经属于公司了))
当其他外界的人有这类问题的时候,那直接找这家公司就可以了,然后公司的声誉越来越高。然而当有一个更好的技术出现,你的技能(函数接口)也将再次被替换掉,你也就被炒鱿鱼了。
"派生"是既希望使用老类的功能,也希望使用老类的接口:
再举个简单的例子:
#include <iostream>
using namespace std;class Parents {
public:
void Parents_Knowledge()
{
//......
}};
class P:public Parents {
//......
};int main()
{
P p;
p.Parents_Knowledge();
return 0;
}这里的P类还是你,只不过这个你年龄还很小,什么都不知道(那个时候你的P类里面什么都没有);
然后你父母开始将他们所有的爱与经验都一点点教给你,你于是也就获得了新的 "public继承属性",但是这些知识终究没有成为你自己的,因为那时的你还小还体会不到那些到底有什么用,但是聪明的你却把它记在了心底。
多年之后,你的专业知识越来越多(你的P类的函数越来越多),但当你真正遇到以前不理解的那些挫折的时候,你才会发现你父母以前教给你的都是有用的。
************************************************************************************************************************************
************************************************************************************************************************************
在组合类自己的构造函数被调用之前,会首先调用成员类的拷贝构造函数来初始化成员类,有几个成员类就调用几次拷贝构造函数;
在组合类的构造函数中如果形参是对象,就会再次调用成员类的拷贝构造函数来实例化形参,这里实例化出来的形参会被在该组合类初始化结束的时候调用成员类的析构函数将其析构掉。
在形参实例化之后会调用组合类自己的构造函数进行实例化组合类自己。
<1> 源码
#include <iostream>
using namespace std;
class Point
{
public:
Point(int xx = 0, int yy = 0) { X = xx; Y = yy; cout << "Point构造函数" << endl; }
Point(Point &p);
~Point()
{
cout << "Destruct Point!" << endl;
}
private:
int X, Y;
};
Point::Point(Point &p)
{
X = p.X;
Y = p.Y;
cout << "Point拷贝构造函数" << endl;
}
class Line
{
public:
Line(){}
Line(Point pp1, Point pp2);//Line构造函数
Line(Line &L);//Line拷贝构造函数
~Line()
{
cout << "Destruct Line!" << endl;
}
private:
Point p1, p2;
double Len;
};
Line::Line(Point pp1, Point pp2) : p1(pp1), p2(pp2)//组合类构造函数初始化
{
/*p1 = pp1;
p2 = pp2;*/
cout << "Line构造函数" << endl;
}
Line::Line(Line &L) : p1(L.p1), p2(L.p2)
{
cout << "Line拷贝构造函数" << endl;
Len = L.Len;
}
int main(int argc, char *argv[])
{
Point Myp1(1, 1);
cout << "*****" << endl;
Line line(Myp1,Myp1);
cout << "+++++" << endl;
Line line2(line);
cout << "-----" << endl;
}
<2>运行结果
<3>分析
① 析构函数和上方的构造函数执行的顺序是相反的(和栈类似)
② 形参在构造被实例化之后,就会在该类初始化结束的时候被释放,只会释放实例化出来的形参对象