我正在尝试管理嵌入式设备上的设备。设备由设备管理器管理。它的职责是确保设备的使用寿命并为设备提供代码的其他部分。
设备有一定的方法(初始化、检查状态等)。为了简单起见,我只添加了 IsReady()。为了让代码更加灵活,我喜欢使用接口。例如,我有一个支持 UART 的 IO 扩展器。所以这个设备实现了 IDevice 但也实现了 IStream 接口。
我可以询问所有与 IStream 兼容的设备。由于我不想依赖 RTTI,因此我使用密钥来实现此目的。 (在示例中,这些是硬编码的)如果这不是必需的,我会更喜欢,但如果没有 RTTI,我不会看到这种情况发生。
当我尝试获取具有特定接口的设备时,问题就出现了。由于该接口本身不继承自 IDevice,因此我无权访问 IDevice 方法。
这是我的问题:我有一个对象,即 std::shared_ptr 现在我想访问 IDevice 定义的方法。由于 IStream 不实现 IDevice,因此我无法访问这些方法。出于同样的原因,我无法使用静态强制转换,并且因为我没有 RTTI,所以无法使用动态强制转换。
我脑海中突然出现的一个解决方案是使用 devicemanager 从 IStream 中获取 IDevice。
这是我试图实现的目标的精简版本:
class IDevice {
public:
virtual bool IsReady() = 0;
};
class IStream {
public:
virtual size_t ReadStream(uint8_t* buffer, size_t bufferSize) = 0;
};
class DeviceManager {
public:
template<typename T>
std::vector<std::shared_ptr<T>> GetDevicesByCompatibility(const std::string& compatibility);
};
class MAX14830_Uart : public IDevice, public IStream {
public:
bool IsReady() override;
size_t ReadStream(uint8_t* buffer, size_t bufferSize) override;
};
void Test()
{
DeviceManager deviceManager; // Not included in example, but the devices are instantiated and registered to the device manager
auto devices = deviceManager.GetDevicesByCompatibility<IStream>("IStream");
for (auto& device: devices)
{
// Here is the problem, I want to check if the device is ready, but my device is of type IStream, not IDevice
if (device->IsReady())
{
}
}
}
这里有几个选项:
deviceManager.CastDevice<IDevice>(ptr, "IDevice");
,这与您现有的方法非常相似。IUnknown
像每个接口都继承自的COM一样。IDevice
用于所有内容,并让它包含类似 GetStream()
的方法,如果接口不可用,则返回 nullptr
。IDevice
,其中包含并非所有设备都有的方法。所有选项 1-3 都添加了一些额外的代码来访问设备。相比之下,4. 是代码量最少且非常易于理解的选项,尽管它在架构上并不干净,并且如果方法数量增加可能会出现问题。