【对象与对象关系介绍、聚合和组合关系中函数代码实例】

对象与对象的关系

在一个系统中,一个对象可能给与不同的对象相关,以下是不同的关系。

  1. 依赖关系(使用一个)
  2. 关联关系(使用一个)
  3. 聚合关系(有一个)
  4. 组合关系(有一个,用…来实现)
  5. 继承关系(是一个)
  6. 类模板

1.依赖(Dependency)

程序类之间的"依赖"关系主要体现出的是一种使用关系,对于两个相对独立的对象,当一个对象负责构造另一个对象的实例,或者当一个对象依赖于另一个对象所提供的服务时,这两个对象之间主要体现为依赖关系。
在类型的设计中,依赖关系主要体现在目标类型的对象(实例),作为当前类型方法的局部对象或者方法的参数类型。

2.关联(Association)

对于两个相互独立的对象,当对象A与另一个对象B存在固定的对应关系时,这两个对象之间为关联关系。关联关系是依赖关系的特例。
在类型的设计中,关联关系主要体现在目标类型的指针(弱关联)或引用(强关联),作为当前类型的属性成员。没有整体和部分的关系,只是有关系而已。

3.关联与聚合

在概念上,它们都是对象实例间的一种静态关系,都是在类的抽象层次上的定义,并且最终都可以通过对象的属性来体现。但它们差别是,聚合关系所涉及的两个类型的对象,在现实世界中的含义有明显的has - a(有一个)的语义**,能够区分哪个是整体,哪个是部分**,而关联所涉及的对象之间没有这种语义,即分不出整体和部分的关系。用…来组成。

class Point // 点
{
private:
  float _x;
  float _y;
public:
  Point():_x(0.0),_y(0.0) {}
  Point(float x,float y):_x(x),_y(y) {}
  Point(const Point &p):_x(p._x),_y(p._y) // 按位拷贝 inline 函数
 {}
  Point & operator=(const Point &p)  // 按位赋值 inline 函数
 {
    if(this != &p)
   {
      _x = p._x;
      _y = p._y;
   }
    return *this;
 }
  ~Point() {}
 
  float & pointX() { return _x;}
  const float & pointX() const { return _x;}
 
  float & pointY() { return _y;}
  const float & pointY() const { return _y;}
};
class Circle
{
private:
  Point _center; // 圆心
  float _radius;  // 半径
};
//此时整体与部分之间是可分离的,它们可以具有各自的生命周期,
//部分可以属于多个整体对象,也可以为多个整体对象共享。

以下代码可以这样写吗?

class Circle
{
private:
  Point _center;
  float _radius;  
};
public:
Ciecle (int r=0,int x=0,int y=0):_radius(r),_center(x,y);
{
_center=(x,y);
cout<<"create Circle ”<<endl;
}

当使用构造函数的类型转换时,单参的构造函数才有类型转换的能力,所以我们需要加上一个point构造函数的缺醒值。
2.构造函数中的初始化使用方案 减少构造函数的调动次数,比构造函数中花括号里赋值的语句要更好。

4.组合
当对象A是对象B的属性时,称对象B包含对象A。意味着"用…来实现,用…来构造"
相比于聚合,组合是一种耦合度更强的关联关系。存在组合关系的类表示"整体-部分"的关联关系,“整体"负责"部分"的生命周期,他们之间是共生共死的;并且“部分"单独存在时没有任何意义。
例如,People与Soul、Body之间是组合关系,当人的生命周期开始时,必须同时有灵魂和肉体;当人的生命周期结束时,灵魂肉体随之消亡;无论是灵魂还是肉体,都不能单独存在,他们必须作为人的组成部分存在。

以下是的exemple是组合和聚合关系中对象六个系统函数在此关系中的使用特点

exemple 1: 类里定义的构造函数中的类类型 成员没有给出初始化,那么不定义其成员,也不在成员的类中给出缺醒值,那么构造函数无法编译通过。

using namespace std;
class point
{
private:
	 float _x;
	 float _y;
public:
	point(float x=0, float y=0) :_x(0), _y(0)//给出缺醒值0
	{
		cout << "Create point " << endl;
		_x = x;
		_y = y;
	}
	point(const point& p1) :_x(p1._x), _y(p1._y)
	{
		cout << "Copy point " << endl;
	}
	void print()
	{
		cout << this->_x << endl;
		cout << this->_y << endl;
	}
	
};


class  rectangle
{
private:
	point leftop;
	point rightbottom;
public:
	rectangle(float x1,float y1,float x2,float y2) :leftop(x1,y1)//,rightbottom(x2,y2)
	//这里不给出rightbottom的初始化
	{
		cout << " Create rectangle" << endl;
	}
	rectangle(point& a, point& b) :leftop(a), rightbottom(b)
	{
		cout << " Create rectangle" << endl;
	}
		rectangle() :leftop(0, 0), rightbottom(0, 0)
	{
		cout << " Create rectangle" << endl;
	}
	
	rectangle(const rectangle& s1) :leftop(s1.leftop),rightbottom(s1.rightbottom)
	{
		cout << " Copy rectangle" << endl;
	}
	void print()
	{
		 this->leftop.print() ;
		 this->rightbottom.print();
	}
};

exemple 2:类里定义的构造函数中的类类型 成员没有给出初始化,成员定义时,其为类型的强转(只能单参),成员的类里也要给出缺醒值:

using namespace std;
class point
{
private:
	 float _x;
	 float _y;
public:
	point(float x=0, float y=0) :_x(0), _y(0)//给出缺醒值0
	{
		cout << "Create point " << endl;
		_x = x;
		_y = y;
	}
	point(const point& p1) :_x(p1._x), _y(p1._y)
	{
		cout << "Copy point " << endl;
	}
	void print()
	{
		cout << this->_x << endl;
		cout << this->_y << endl;
	}
	
};


class  rectangle
{
private:
	point leftop;
	point rightbottom;
public:
	rectangle(float x1,float y1,float x2,float y2) :leftop(x1,y1)//,rightbottom(x2,y2)
	{
	    rightbottom(x2,y2)//类型的强转,必须是单参。这里只有一个值是有效的。
		cout << " Create rectangle" << endl;
	}
	rectangle(point& a, point& b) :leftop(a), rightbottom(b)
	{
		cout << " Create rectangle" << endl;
	}
		rectangle() :leftop(0, 0), rightbottom(0, 0)
	{
		cout << " Create rectangle" << endl;
	}
	
	rectangle(const rectangle& s1) :leftop(s1.leftop),rightbottom(s1.rightbottom)
	{
		cout << " Copy rectangle" << endl;
	}
	void print()
	{
		 this->leftop.print() ;
		 this->rightbottom.print();
	}
};
int main()
{
	rectangle r3(20,2,60,6);
	rectangle r1(10,20,30,35);
	r1 = r3;
	r1.print();
	return 0;
}

打印结果分析: 构造函数中的rightbottom(x2,y2),将y2最先传入(从右向左传),因为类型转换是单参,x2没有利用,最后的结果“0”是构造函数给出的缺醒值;
在这里插入图片描述


exemple 3:拷贝构造函数中类类型 成员没有给出初始化,则调动的是成员类型的构造函数而不是拷贝构造;

拷贝构造函数可以设置不完全拷贝对象的值而自己定义,但要给出缺醒值。

using namespace std;
class point
{
private:
	 float _x;
	 float _y;
public:
	point(float x=3, float y=8) :_x(0), _y(0)
	{
		cout << "Create point " << endl;
		_x = x;
		_y = y;
	}
	point(const point& p1) :_x(p1._x), _y(p1._y)
	{
		cout << "Copy point " << endl;
	}
	
};


class  rectangle
{
private:
	point leftop;
	point rightbottom;
public:
	rectangle(float x1,float y1,float x2,float y2) :leftop(x1,y1),rightbottom(x2,y2)
	{
		cout << " Create rectangle" << endl;
	}
	rectangle(point& a, point& b) :leftop(a), rightbottom(b)
	{
		cout << " Create rectangle" << endl;
	}
		rectangle() :leftop(0, 0), rightbottom(0, 0)
	{
		cout << " Create rectangle" << endl;
	}
	
	rectangle(const rectangle& s1) :leftop(s1.leftop)//,rightbottom(s1.rightbottom)
	{
		rightbottom=(7, 7);
		cout << " Copy rectangle" << endl;
	}

};
int main()
{
	rectangle r3(20,2,60,6);
	rectangle r1(r3);
	r1.print();
	return 0;
}

打印结果:(7 和 8的结果是我们自己定义的而不是拷贝得来)
在这里插入图片描述


exemple 4:赋值函数中类类型 成员没有给出初始化,则可能根据用户的自己定义而赋值一部分,另一部分自己定义;

using namespace std;
class point
{
private:
	 float _x;
	 float _y;
public:
	point(float x=3, float y=8) :_x(0), _y(0)
	{
		cout << "Create point " << endl;
		_x = x;
		_y = y;
	}
	point(const point& p1) :_x(p1._x), _y(p1._y)
	{
		cout << "Copy point " << endl;
	}

	
};


class  rectangle
{
private:
	point leftop;
	point rightbottom;
public:
	rectangle(float x1,float y1,float x2,float y2) :leftop(x1,y1),rightbottom(x2,y2)
	{
		cout << " Create rectangle" << endl;
	}
	rectangle(point& a, point& b) :leftop(a), rightbottom(b)
	{
		cout << " Create rectangle" << endl;
	}
		rectangle() :leftop(0, 0), rightbottom(0, 0)
	{
		cout << " Create rectangle" << endl;
	}
	
	rectangle(const rectangle& s1) :leftop(s1.leftop),rightbottom(s1.rightbottom)
	{
	
		cout << " Copy rectangle" << endl;
	}
	~rectangle() 
	{
		cout << " Destroy rectangle" << endl;
	}
	rectangle& operator=(const rectangle &r1)
	{
		leftop = r1.leftop;
		//rightbottom = r1.rightbottom;
		cout << "operator =" << endl;
		return *this;
	}


};
int main()
{
	
	rectangle r3(20,2,60,6);
	rectangle r1(1,1,1,1);
	r1 = r3;
	r1.print();
	return 0;
}

打印结果:(赋值了一部分而已)
在这里插入图片描述

5.继承关系


版权声明:本文为lmy347771232原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。