类之间的关系(1. 使用关系和组合关系)
来源:互联网 发布:java overload 编辑:程序博客网 时间:2024/05/16 00:42
- 类之间的关系
- 使用关系
- 组合关系
- 例子
- 参考
- 组合关系中的构造函数和析构函数的调用顺序
- 组合关系中调用成员的带参数的构造函数
- 例子
类之间的关系
之前的章节我们介绍了单个类有关的知识。在程序中如果出现多个类,那么它们之间会表现出一定的关系。粗略的看,类之间有以下几种关系:
- 使用关系
- 组合关系
- 继承关系
使用关系
使用关系是比较弱的关系,就是说A类使用了B类的功能(方法),在代码层面,A类可能以如下方式使用了B类:
B类出现在A类成员方法的参数里
class A{ public: void method1(B b) { // ... }};
B类出现在A类成员方法里
class A{ public: void method2() { B b; // ... } };
在UML即软件开发建模语言领域,使用关系被称为依赖(Dependency)关系,其UML类图表示为:
表示A类使用了B类,注意连线是虚线。
在类之间的UML图中,有时因为依赖关系是比较弱的关系,可能就不会表示出来了(绘制虚线)。(???待确认)
使用关系是两个类之间的临时关系。上述例子中只有A类对象调用了method1
或者method2
方法,才会用到B类。
这就区别于类之间另一种“更强”的关系,组合关系。
组合关系
组合关系指A类的一个成员是B类的对象,换句话说,A类对象的某一个属性保存在B类对象中。组合关系也可以称为包含关系。
代码层面
class A{ private: B b; // ...};
在UML中,组合关系被称为关联(Association)关系,其UML类图表示为:
表示A1类的一个成员是B1类的。注意连线是实线。
相比于使用关系,组合关系是长期的关系。A类的一个成员是B类的,因此A类对象包含了一个B类对象。所以这种关系称为“组合”,组合关系也被形象地称为“有一个(has a)”关系。
聚合关系类似于组合关系,只是包含的含义更加深刻,在此不加介绍。我们目前只需要了解到组合的含义就可以了。
例子
Human类的例子
#include <iostream>#include <string> class Human { public: void introduce() { cout << ... } private: string name; ...};
Human类的成员函数introduce中使用了cout,而cout是输出类ostream类的对象,因此Human类使用了ostream类。
Human类的成员变量name是string类的对象,因此Human包含了string类。
参考
- Understanding UML Class Relationships
组合关系中的构造函数和析构函数的调用顺序
A类含有B类成员,那么在构造A类对象的时候也会构造成员之一的B类对象。
class B{ public: B() { cout << "Construction B is called" << endl; } ~B() { cout << "Destruction B is called" << endl; } private: int x;};class A{ public: A() { cout << "Construction A is called" << endl; } ~A() { cout << "Destruction A is called" << endl; } private: B b; // A含有B类成员b};int main(){ { A a; cout << endl; } return 0;}
上述代码在main函数中将对象a创建在一对大括号中是因为大括号在程序中是一个作用域的标志,进入和退出这个区域,它里面的对象就会被创建和销毁,因此我们能及时地看到a的析构函数的调用。
可见,程序会先调用成员b的构造函数,然后再调用A类的构造函数,遵循先部分,后整体的创建顺序。对象销毁是,析构函数执行顺序相反,先调用A类的析构函数,再调用成员b的析构函数,先整体,后部分。
组合关系中调用成员的带参数的构造函数
class B{ public: B(int x_) { x = x_; cout << "Construction B is called, x = " << x << endl; } private: int x;};
类B有一个带参数的构造函数。那么创建B类对象b时,需要这样B b(5);
,这样才会调用该构造函数。
此时,如果A类成员b是B类类型的,那么怎样在A类的构造函数中初始化b呢?
在A类的构造函数中使用成员初始化列表来调用B类的带参数的构造函数。
class B{ public: B(int x_) { x = x_; cout << "Construction B is called, x = " << x << endl; } private: int x;};class A{ public: A(int x) : b(x) // 构造函数的成员初始化列表,调用b的构造函数 { cout << "Construction A is called" << endl; } private: B b; // ...};int main(){ A a(10); // 10是提供给成员b的构造函数的 return 0;}
构造函数的成员初始化列表是初始化类的成员的地方,可在那里指定调用成员的“某款”构造函数。
如果B类存在不带参数的构造函数,即默认构造函数,那么可以不使用成员初始化列表来初始化b。此时,创建成员b调用的就是B类默认构造函数,就像在“调用顺序”中的例子展示的那样。
注意,如果B类只含有带参数的构造函数,而没有默认构造函数,那么在A类的构造函数中一定要使用成员初始化列表来初始化b。
例子
Date类只有一个带参数的构造函数
class Date{ public: Date(int y, int m, int d) { year = y; month = m; day = d; } int year, month, day;};
那么包含它的类需要在构造函数中使用成员初始化列表来初始化它。
class Human{ public: Human(string n, ..., int y, int m, int d) : birthday(y, m, d) { ... } Date birthday; string name; ...};
- 类之间的关系(1. 使用关系和组合关系)
- 类之间的关系-- 关联、组合、聚合、依赖关系比较
- 类和类之间的依赖、关联、聚合、组合关系
- 和之间的关系
- 类的组合关系
- 1.类之间的关系
- UML类图中的关系介绍(依赖关系、泛化关系、关联关系(聚合和组合)、实现关系)
- gpio_direction_output 和 gpio_set_value之间的使用关系
- gpio_direction_output 和 gpio_set_value之间的使用关系
- 类之间的关系
- 类之间的关系
- 类之间的关系
- 类之间的关系
- 类之间的关系
- 类之间的关系
- 类之间的关系
- 类之间的关系
- 类之间的关系
- php安装过程出现的问题
- [BZOJ3697]采药人的路径(点分治)
- MyBatis Generator
- 常用cmd命令(持续更新...)
- Java 8中你可能没用过的10个特性
- 类之间的关系(1. 使用关系和组合关系)
- Redis介绍以及安装(Linux)
- SQL语句分页查询模板
- 06异常处理
- case when 函数使用中遇到的问题
- Vue.js开发环境的搭建
- socket中本地主机与远程主机的IP地址和端口号的确定
- go语言坑之for range
- 【Android】多渠道打包,其实可以更快