安全地在C ++中传递对抽象类的引用

时间:2016-08-25 12:10:04

标签: c++ design-patterns reference abstract-class

我正在为数据收集控制器开发一个应用程序。它必须 接口与许多不同的其他设备,反过来可能提供 不同类型和数量的数据。为此,以下层次结构是 设计(它有点冗长但跟我一起):

  • 信息的基本单位是基准。 Datum本身就是一个摘要 class,其后代表示不同类型的[物理] 数量:温度,压力,能量,功率,继电器状态等。每个数据 instance表示单个读数(在某个时刻)。

  • 数据由Device收集,而IO s又包含多个Device s。一个装置 instance代表一个具体的物理数据收集设备;它的班级(a 抽象void Device::update()类的后代)代表设备和模型 包含与其接口所需的所有特定于模型的代码 从中提取读数。这是通过调用虚函数IO来完成的。

  • 每个IO::get_value()实例代表设备收集的变量。例如, 如果设备是多通道温度监控器,则IO代表a 单个传感器连接到设备。可以通过查询值来查询IO 调用Datum,返回Node

  • 最后, <tr ng-repeat="(key, value) in data"> <td> {{key}} </td> <td> {{ value }} </td> </tr> 类保留了附加到的所有设备的列表 控制器,这些设备中所有IO的另一个列表,并提供方法 一次轮询所有设备,单个设备,单个IO等。

这些关系(有点松散地)反映在下图中:

Diagram of class relations

现在,问题本身:

在所有这些中,很多抽象后代的实例 类必须一直传递并存储: Node 存储它 设备及其 IO 设备自己将 IO 存储为 好吧,数据被创建并返回并传递和销毁 设备和IO列表更新到位,等等。但目前还不清楚如何 实现所有这些传递:

  • 按值传递抽象类的实例显然是不可能的,并且 即使它不是抽象的,也可能导致对象切片。
  • 通过引用传递它们为函数的参数工作,但是怎么样 创建和返回Datum实例?它们被创建为局部变量 IO :: get_value方法等在返回时被销毁。 此外,无法存储引用,例如在std :: map。
  • 最后,传递指针很危险。为了返回一些东西 指针一必须在方法中分配内存,然后它就是调用者的内存 在不再使用返回值后释放内存的业务。在 除了不方便之外,它还有一种危险 内存泄漏,双重释放,或者程序的其他部分 取消引用预先存储在那里的现在空指针。

所以我不知道如何实现强大的交换系统 像这样的对象,用或多或少的万无一失的方式来确保对象 表现为一个由价值传递的变量(只要它们存在就会存在 需要,但不会更长)同时保留继承提供的鸭子类型 共同界面。

1 个答案:

答案 0 :(得分:1)

使用std::unique_ptr获取唯一所有权,使用std::shared_ptr获取共享所有权。这使得传递指针更加安全。

std :: unique_ptr无法复制,并且当unique_ptr被销毁时(例如超出范围),指向对象会自动释放。相反,可以复制std :: shared_ptr,并且只有在销毁shared_ptr的所有副本时才会释放指向的对象。

如果您使用上述工具编写代码并使用std::make_unique(C ++ 14)和std::make_shared(C ++ 11),则基本上不需要手动new和{ {1}}并避免许多与内存相关的问题。