我正在为数据收集 Controller 开发一个应用程序。它必须 与许多不同的其他设备接口(interface),这反过来可能提供 不同类型和数量的数据。为此,以下层次结构是 设计(有点长,但请耐心等待):
信息的基本单位是数据。
Datum
本身就是一个抽象 类,其后代代表不同类型的[物理] 数量:温度、压力、能量、功率、继电器状态等。每个数据 实例代表单个读数(在某个时刻)。数据由
Device
收集,后者又包含多个IO
。一个装置 实例代表一个具体的物理数据收集设备;它的类(一个 抽象Device
类的后代)表示设备的模型和 包含与其交互所需的所有特定于模型的代码,并且 从中提取读数。这是通过调用虚函数void 来完成的 设备::更新()
。每个
IO
实例代表一个设备收集的变量。例如, 如果设备是多 channel 温度监控器,那么一个 IO 代表一个 连接到设备的单个传感器。可以通过以下方式查询 IO 的值 调用IO::get_value()
,返回一个Datum
。最后,
Node
类保留了所有附加到 Controller ,这些设备中所有 IO 的另一个列表,并提供方法 一次轮询所有设备、单个设备、单个 IO 等。
这些关系(有点松散地)反射(reflect)在下图中:
现在,对于问题本身:
在所有这一切中,有很多抽象后代的实例 类必须一直传递和存储:Node 存储它的 设备及其IO,设备本身将自己的IO存储为 好吧,数据被创建、返回、传递和销毁, 设备和 IO 列表得到更新等。但目前尚不清楚如何 实现所有这些传递:
- 按值传递抽象类的实例显然是不可能的,并且 即使它们不是抽象的,也可能导致对象切片。
- 通过引用传递它们适用于函数的参数,但是呢 创建和返回 Datum 实例?它们被创建为局部变量 IO::get_value 方法等在返回时被销毁。 此外,不可能存储引用,例如在 std::map 中。
- 最后,传递指针是危险的。为了返回一些东西作为 指针一必须在方法中分配内存,然后是调用者的 业务在返回值不再使用后释放内存。在 除了不方便之外,它还存在获得 内存泄漏、双重释放或程序的其他部分 取消引用预先存储在那里的现在为空的指针。
所以我不知道如何实现一个强大的交换系统 像这样的对象,用或多或少的万无一失的方法来确保对象 表现为按值传递的变量(只要它们存在,就一直存在 需要,但不再需要),同时保留继承提供的鸭子类型 一个通用接口(interface)。
最佳答案
使用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
和 delete
并避免了很多与内存相关的问题。
关于c++ - 在 C++ 中安全地传递对抽象类的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39144955/