这可能是因为我不完全理解C ++中的接口是如何工作的,但是我们走了:
我在QT5中有一个属性类的基接口。
class IBaseProperty
{
public:
virtual ~IBaseProperty() {}
// Returns the property key as a string.
virtual QString getKey() = 0;
// Returns the property value as a raw string.
virtual QString getValueRaw() = 0;
// Sets the property key as a string.
virtual void setKey(QString key) = 0;
// Sets the property value as a raw string.
virtual void setValueRaw(QString value) = 0;
};
我还有一个模板化的接口扩展,以便更容易地子类化处理更具体数据类型的属性。
template <class T>
class IProperty : public IBaseProperty
{
public:
virtual ~IProperty() {}
// Classifies a property with a Property_t identifier.
virtual Property_t getPropertyType() = 0;
// Returns the property value as the specified type.
// Bool is true if conversion was successful.
virtual T getValue(bool* success) = 0;
// Sets the property value as the specified type.
virtual void setValue(T value) = 0;
// Returns whether the current value can be converted correctly
// to the specified type.
virtual bool canConvert() = 0;
};
我的基本属性(仅实现IBaseProperty)如下所示:
class BaseProperty : public QObject, public IBaseProperty
{
Q_OBJECT
public:
explicit BaseProperty(QObject *parent = 0, QString key = "", QString value = "");
virtual QString getKey();
virtual QString getValueRaw();
public slots:
virtual void setKey(QString key);
virtual void setValueRaw(QString value);
protected:
QPair<QString, QString> m_Property; // KV pair this property holds.
};
我将它子类化为一个字符串属性 - 显然base属性只能返回字符串,但我想在string / int / float / etc之间保持相同的函数格式。通过在所有这些中允许getValue来实现属性。在这种情况下,GetValue只是调用getValueRaw来返回值。
class StringProperty : public BaseProperty, public IProperty<QString>
{
Q_OBJECT
public:
explicit StringProperty(QObject *parent = 0, QString key = "", QString value = "");
virtual inline Property_t getPropertyType() { return Prop_String; }
virtual QString getValue(bool* success);
virtual bool canConvert();
public slots:
virtual void setValue(QString value);
};
当我实现getValue和setValue:
时会出现歧义inline QString StringProperty::getValue(bool* success)
{
*success = canConvert();
return getValueRaw(); // This line causes the ambiguity.
}
编译器抱怨:
C2385:'getValueRaw'的模糊访问:可能是'getValueRaw' 在base'BaseProperty'中,或者可以是base中的'getValueRaw' 'IBaseProperty'。
我不完全确定在这种情况下该怎么做 - 我原以为IBaseProperty是一个纯虚拟类意味着无论如何都无法从这一点调用该函数,因此只能调用实施的地方(BaseProperty)。解决这个问题的正确做法是什么?我不确定我应该从哪个基类调用该函数。
答案 0 :(得分:2)
首先看,它似乎是经典的diamond problem or diamond inheritance
String property
继承自BaseProperty
和IProperty
,并且两者都具有相同的基类IBaseProperty
。这就是为什么会有歧义。
答案 1 :(得分:0)
问题是StringProperty
包含两个类型为IBaseProperty
的基类子对象。您可能只需要一个IBaseProperty
,在这种情况下,您需要使用虚拟继承。 (将“接口”作为虚拟基类通常是一个好主意。)
template <class T>
class IProperty : public virtual IBaseProperty
{ /*...*/ };
class BaseProperty : public virtual IBaseProperty, public QObject
{ Q_OBJECT; /*...*/ };
class StringProperty : public virtual IProperty<QString>, public BaseProperty
{ Q_OBJECT; /*...*/ };