C++ 如何向对象添加属性而不破坏其父接口?

C++ 如何向对象添加属性而不破坏其父接口?,c++,qt,C++,Qt,我和我的团队正在研究的代码库用于引导物理设备(分光光度计)。它们都非常相似,但有些可以做其他人不能做的事情,它们都有自己的SDK和驱动程序 我们经常需要支持新的设备,每个设备都有自己的特定属性 主设备接口,比如IDevice,有很多纯虚拟接口,用于确定设备(比如Device1、Device2等)是否可以执行给定的操作,或者它支持什么类型的操作 IDevice.h class IDevice : public QObject { Q_OBJECT public: virtual ~

我和我的团队正在研究的代码库用于引导物理设备(分光光度计)。它们都非常相似,但有些可以做其他人不能做的事情,它们都有自己的SDK和驱动程序

我们经常需要支持新的设备,每个设备都有自己的特定属性

主设备接口,比如IDevice,有很多纯虚拟接口,用于确定设备(比如Device1、Device2等)是否可以执行给定的操作,或者它支持什么类型的操作

IDevice.h

class IDevice : public QObject {
    Q_OBJECT
public:
    virtual ~IDevice() {}
    virtual bool canDoOperationA()   = 0;
    virtual bool canDoOperationB()   = 0;
    virtual QVariant supportedMode() = 0;

    // etc. There are a lot of these ‘canDo’ and ‘supported’ interfaces.

    // dozens of other things, slots, signals, etc.
};
class IDevice : public QObject {
    Q_OBJECT
public:
     virtual ~IDevice() {}
     virtual bool canDoOperationA() = 0;
     virtual bool canDoOperationB() = 0;
     virtual QVariant supportedMode() = 0;
     virtual bool canDoOperationC() = 0;
     virtual QVariant supportedSpecialMode() = 0;
};
设备1.h

class Device1 : public IDevice {
public:
     bool canDoOperationA()   { return true; }
     bool canDoOperationB()   { return false; }
     QVariant supportedMode() { return QStringList{{ “m1”, “m2” }}; }
};
设备2.h

class Device2 : public IDevice {
public:
     bool canDoOperationA()   { return false; }
     bool canDoOperationB()   { return true; }
     QVariant supportedMode() { 
         return getModesAtRuntime(); 
     }

private:
     QVariant getModesAtRuntime() {
         /* determine at runtime what modes are supported,
            depending on the device current configuration */
        return QVariant();
     }
} ;
这些属性中的大多数在编译时已知,但其中一些属性(取决于设备)必须在运行时确定(通常通过设备SDK,该SDK允许询问设备本身的状态)

通常,我们需要支持新的设备和/或属性,从而在IDevice中添加其他canDoOperationXXX方法(随着时间的推移变得异常)。例如,如果操作C和特殊模式需要特定设备支持,IDevice将类似于:

IDevice.h

class IDevice : public QObject {
    Q_OBJECT
public:
    virtual ~IDevice() {}
    virtual bool canDoOperationA()   = 0;
    virtual bool canDoOperationB()   = 0;
    virtual QVariant supportedMode() = 0;

    // etc. There are a lot of these ‘canDo’ and ‘supported’ interfaces.

    // dozens of other things, slots, signals, etc.
};
class IDevice : public QObject {
    Q_OBJECT
public:
     virtual ~IDevice() {}
     virtual bool canDoOperationA() = 0;
     virtual bool canDoOperationB() = 0;
     virtual QVariant supportedMode() = 0;
     virtual bool canDoOperationC() = 0;
     virtual QVariant supportedSpecialMode() = 0;
};
然后,所有设备都需要更新和重新编译(它们甚至不知道OperationC和SpecialMode)。我认为这是一个设计缺陷

我想知道是否有一种在不破坏API的情况下在设备中添加新属性的最佳方法

我正在考虑从IDevice中删除所有canDoOperation和supportedModes方法,并用单个接口替换它们

QVariant getProperty(const QString& propertyName) = 0;
这样,设备返回自己的属性,无论是运行时还是编译时。如果不支持属性,则返回无效的QVariant。向特定设备添加特定属性不会破坏API,只会重新编译设备


这种方法有什么警告吗?您认为有更好的方法解决此问题吗?

QObject已经具有运行时可编辑属性。请参阅和@Caleth。问题是某些属性无法存储,但必须在运行时计算。据我所知,我不能使用QObject::property来实现这一点。你理解错了<代码>QObject::setProperty使用以前未看到的名称添加该属性
QObject::property
与以前未看到的名称一起返回空的
QVariant
在某些情况下,我每次都需要从设备本身(通过其SDK)读取属性,因为它们的值会随时间而变化。我可以使用QObject::setProperty设置这些属性,但是每次更改时都应该更新它们。每个设备都会维护自己的属性列表。这可能是一个解决方案。这是一个广泛的主题。解决这个问题的方法有上千种。除了个人意见之外,你不会得到令人满意的答案。作为介绍,您可能希望检查并进一步了解如何实现该目标。QObject已经具有运行时可编辑属性。请参阅和@Caleth。问题是某些属性无法存储,但必须在运行时计算。据我所知,我不能使用QObject::property来实现这一点。你理解错了<代码>QObject::setProperty使用以前未看到的名称添加该属性
QObject::property
与以前未看到的名称一起返回空的
QVariant
在某些情况下,我每次都需要从设备本身(通过其SDK)读取属性,因为它们的值会随时间而变化。我可以使用QObject::setProperty设置这些属性,但是每次更改时都应该更新它们。每个设备都会维护自己的属性列表。这可能是一个解决方案。这是一个广泛的主题。解决这个问题的方法有上千种。除了个人意见之外,你不会得到令人满意的答案。作为一个介绍,你可能想检查一下,并进一步教育自己如何做到这一点。