无需 RTTI C++ 即可转换智能指针

问题描述 投票:0回答:1

我正在尝试管理嵌入式设备上的设备。设备由设备管理器管理。它的职责是确保设备的使用寿命并为设备提供代码的其他部分。

设备有一定的方法(初始化、检查状态等)。为了简单起见,我只添加了 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())
        {
            
        }
    }
}

c++ casting embedded shared-ptr rtti
1个回答
0
投票

这里有几个选项:

  1. 添加一个
    deviceManager.CastDevice<IDevice>(ptr, "IDevice");
    ,这与您现有的方法非常相似。
  2. 使
    IUnknown
    像每个接口都继承自的COM一样。
  3. 如果您不需要外部代码添加新接口,则可以将
    IDevice
    用于所有内容,并让它包含类似
    GetStream()
    的方法,如果接口不可用,则返回
    nullptr
  4. 保持简单并制作一个大“丑陋”
    IDevice
    ,其中包含并非所有设备都有的方法。

所有选项 1-3 都添加了一些额外的代码来访问设备。相比之下,4. 是代码量最少且非常易于理解的选项,尽管它在架构上并不干净,并且如果方法数量增加可能会出现问题。

© www.soinside.com 2019 - 2024. All rights reserved.