如何检查对象是否可转换?

问题描述

我有以下课程:

class ATemperatureDevice{};
class AHumidityDevice{};

class BluetoothLeDevice{};

class Sensor1 : BluetoothLeDevice,ATemperatureDevice,AHumidityDevice {};
class Sensor2 : BluetoothLeDevice,AHumidityDevice  {};

我有一个 vector<BluetoothLeDevice*>,用于存储所有设备。

类 ATemperatureDevice、AHumidityDevice 和 BluetoothLeDevice 具有虚拟功能

当我选择一个时,我有一个 BluetoothLeDevice。现在我想检查它是否来自 ATemperatureDevice 和/或 AHumidityDevice。

我尝试了 dynamic_cast,当它不可强制转换时,我应该得到 null 但是,它说“'dynamic_cast'不允许与 -fno-rtti 一起使用”,尽管它们具有虚函数

检查和投射的最佳方式是什么?

解决方法

正如人们已经评论过的那样,在 T 中存储多态对象 std::vector<T> 会导致对象切片。您的代码在 C# 中有意义,但在 C++ 中,人们倾向于尽可能使用 composition over inheritance 来避免此类问题。在您的情况下,这可能如下所示:https://godbolt.org/z/xna1vjnWh

,

如果不允许使用 dynamic_cast,则存储标记以标识派生类。

//  Test sample
#include <iostream>

using namespace std;
class BluetoothLeDevice
{
public:
    enum class DerivedClassMetaInfo
    {
        Sensor1Tag,Sensor2Tag
    };

    virtual ~BluetoothLeDevice()
    {
    }



    virtual DerivedClassMetaInfo tag(void) const = 0;

    template <typename TargetType>
    TargetType& to()
    {
        if (TargetType::static_tag != tag())
            throw "Convertion failed";
        return static_cast<TargetType&>(*this);
    }
};

class Sensor1 : public BluetoothLeDevice
{
public:
    static const BluetoothLeDevice::DerivedClassMetaInfo static_tag = BluetoothLeDevice::DerivedClassMetaInfo::Sensor1Tag;
    void show()
    {
        cout << "Sensor1 message" << endl;
    }
    virtual DerivedClassMetaInfo tag(void) const override
    {
        return static_tag;
    }
};


int main()
{
    BluetoothLeDevice* temp = new Sensor1();

    Sensor1& sens = temp->to<Sensor1>();
    sens.show();
    delete temp;
    return 0;
}

注意:请谨慎使用此代码,因为它不会处理棘手的继承树。但是你可以很容易(我猜)改进它