在本章中,我们学习了两种对象之间的一些不同类型的关系。
总结
用更简单的对象构建复杂对象的过程称为对象组合。对象组合有两种类型:复合和聚合。
当类的成员与该类具有部分-整体关系时,即存在复合。在复合关系中,类管理成员的存在。要符合复合条件,一个对象和一部分必须具有以下关系:
- 部分(成员)是对象(类)的一部分
- 该部分(成员)一次只能属于一个对象(类)
- 该部分(成员)的存在由对象(类)管理
- 部分(成员)不知道对象(类)的存在
复合通常通过普通成员变量实现,或者通过类管理所有内存分配和解除分配的指针实现。如果您可以将一个类实现为复合,那么您就应该将其实现为复合。
当类与成员具有“拥有-一个”关系时,即存在聚合。在聚合关系中,类不管理成员的存在。要符合聚合条件,一个对象及其部分必须具有以下关系:
- 部分(成员)是对象(类)的一部分
- 该部分(成员)一次可以属于多个对象(类)
- 该部分(成员)的存在不由对象(类)管理
- 部分(成员)不知道对象(类)的存在
聚合通常通过指针或引用实现。
关联是一种更松散的关系类型,其中类使用一个否则不相关的对象。要符合关联条件,一个对象和关联对象必须具有以下关系:
- 关联对象(成员)与对象(类)之间没有其他关系
- 关联对象(成员)一次可以属于多个对象(类)
- 关联对象(成员)的存在不由对象(类)管理
- 关联对象(成员)可能知道或不知道对象(类)的存在
关联可以通过指针或引用实现,或者通过更间接的方式(例如持有关联对象的索引或键)实现。
在依赖中,一个类使用另一个类来执行任务。依赖类通常不是使用它的类的成员,而是临时创建、使用然后销毁,或者从外部源传递到成员函数。
在容器类中,一个类提供一个容器来容纳另一种类型的多个对象。值容器是存储其所持有的对象副本的复合。引用容器是存储指向容器外部对象的指针或引用的聚合。
std::initializer_list 可用于实现构造函数、赋值运算符以及接受列表初始化参数的其他函数。std::initializer_list 位于 <initializer_list> 头文件中。
属性\类型 | 组合 | 聚合 | 关联 | 依赖 |
---|---|---|---|---|
关系类型 | 整体/部分 | 整体/部分 | 其他不相关 | 其他不相关 |
成员可以属于多个类 | 否 | 是 | 是 | 是 |
成员存在由类管理 | 是 | 否 | 否 | 否 |
方向性 | 单向 | 单向 | 单向或双向 | 单向 |
关系动词 | 属于 | 拥有 | 使用 | 依赖于 |
小测验时间
本章非常直接,比前几章更抽象一些,所以这个测验会简短而切中要害。
- 以下描述了哪种关系类型(复合、聚合、关联或依赖)?
1a) 一个 Animal 类,包含动物类型(枚举)和名称(字符串)。
显示答案
1b) 一个文本编辑器类,带有一个 save() 函数,该函数接受一个 File 对象作为参数。save() 函数将编辑器内容写入磁盘。
显示答案
1c) 一个 Adventurer 类,可以携带各种类型的 Item,例如剑、魔杖、药水或咒语书。这些 Item 可以被其他 Adventurer 丢弃和捡起。
显示答案
1d) 玩家在一个神龛祈祷(以获得新的力量)。
显示答案
1e) 一个 Computer 类,包含一个 CPU 类。CPU 可以从 Computer 中移除并单独测试。
显示答案
1f) 铁匠有一个特定的铁砧用于工作。
显示答案
- 选择一项:如果你可以使用(选择一项:复合、聚合、关联或依赖)设计一个类,那么你就应该这样做。