章节目录

第23章总结

本节阅读量:

在本章中,我们学习了两个对象之间的一些关系。

从简单对象构建复杂对象的过程称为对象组合。有两种类型的对象组合:组合和聚合。

当类的成员与该类有部分与整体关系时,就存在组合关系。在组合关系中,类管理成员的存在。要符合组合的条件,对象和部分必须具有以下关系:

  1. 部件(成员)是对象(类)的一部分
  2. 部件(成员)一次只能属于一个对象(类)
  3. 部件(成员)的存在由对象(类)管理
  4. 部件(成员)不知道对象(类)的存在

组合通常通过普通成员变量来实现。如果类的成员变量是指针,则该类需要负责对应的内存分配和销毁。如果可以将类实现为组合,则应该优先使用组合。

当类与成员是“有一个”关系时,存在聚合关系。在聚合关系中,类不管理成员的存在。要符合聚合的条件,对象及其部分必须具有以下关系:

  1. 部件(成员)是对象(类)的一部分
  2. 部件(成员)可以同时属于多个对象(类)
  3. 部件(成员)的存在不由对象(类)管理
  4. 部件(成员)不知道对象(类)的存在

聚合关系通常通过指针或引用来实现。

关联是一种更松散的关系类型。在关联关系中,类会使用其他不相关的对象。要符合关联的条件,对象和关联对象必须具有以下关系:

  1. 被关联的对象(成员)与当前对象(类)无整体/部分的关系
  2. 被关联的对象(成员)可以同时属于多个对象(类)
  3. 被关联的对象(成员)的生命周期不被当前对象(类)管理
  4. 被关联的对象(成员)可能也可能不知道当前对象(类)的存在

关联关系通常通过指针或引用实现,也可以通过更间接的手段实现(例如存储数组中的位置等)。

在依赖关系中,一个类会使用其它类来完成任务。但是这两个类通常都不是对方的成员,被依赖的类一般会被临时创建、使用并销毁,或者从其它外部来源传入当前函数。

在容器类中,一个类提供了一个容器来容纳另一类型的多个对象。值容器是一种组合关系,用于存储它所持有的对象的拷贝。引用容器是一种聚合关系,它存储指向容器外部的对象的指针或引用。

std::initializer_list 可用于实现构造函数、赋值运算符以及其它需要接收初始化列表的函数。std::initializer_list 位于 <initializer_list> 头文件中。

属性 组合 聚合 关联 依赖
关系类型 部分-整体 部分-整体 相互关联 依赖
成员可以属于多个类 否 是 是 是
成员生命周期由类管理 是 否 否 否
关系指向 单向 单向 单向或双向 单向
关系术语 一部分 有一个 使用一个 依赖于

习题

本章内容比较直接,也比前几章更抽象一些,因此本章的测验会简短一些,直奔主题。

问题 1

下列各种描述分别属于哪种关系(组合、聚合、关联还是依赖)?

1a) 一个Animal类,其中包含动物类型(枚举)和名字(string)。

查看答案

组合——动物类型和名字在Animal之外没有用处。

1b) 一个文本编辑器类,其save()函数接受一个File对象作为实参,save()函数把编辑器的内容写到磁盘上。

查看答案

依赖——文本编辑器类为了完成「保存到磁盘」这个任务而使用了File对象。

1c) 一个Adventurer类,可以携带各种Item,例如剑、法杖、药水或法术书。这些Item可以被其他Adventurer丢弃或拾取。

查看答案

关联——Adventurer与Item之间不是「整体-部分」关系,因此这不是聚合。Adventurer「使用」Item,但不管理它们的存亡。

1d) Player在Shrine(神殿)中祈祷以获得新的能力。

查看答案

依赖——Player依赖神殿来获得能力,但与它没有任何长期关联。

1e) 一个Computer类,其中包含一个CPU类。这个CPU可以从Computer上拆下来单独测试。

查看答案

聚合——计算机「拥有」一个CPU,但不管理它的存亡。

1f) 铁匠有一块特定的铁砧,用来完成他的工作。

查看答案

关联——铁匠使用这块铁砧,但与它之间不是「整体-部分」关系。

问题 2

选择一项:如果能够把一个类设计为某种关系(从组合、聚合、关联、依赖中选一项),那就应当这样做。

查看答案

组合


23.6 std::initializer_list

上一节

24.0 继承简介

下一节


本节目录