【问题标题】:C++ interface class causes ambiguous function call (Qt)C++ 接口类导致不明确的函数调用(Qt)
【发布时间】:2013-06-28 13:23:27
【问题描述】:

这可能是因为我没有完全理解 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.
};

我将其子类化以创建一个字符串属性 - 显然基本属性只能返回字符串,但我想在字符串/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” 在基础“BaseProperty”中,或者可能是基础中的“getValueRaw” 'IBaseProperty'。

我不完全确定在这种情况下该怎么做 - 我原以为 IBaseProperty 是一个纯虚拟类意味着无论如何都无法从这一点调用该函数,因此只能从它是在哪里实现的(BaseProperty)。解决此问题的正确措施是什么?我不确定应该从哪个基类调用该函数。

【问题讨论】:

  • 您可能应该用粗体突出/设置您问题的这一部分:Of course I could always qualify with BaseProperty:: or IBaseProperty:: to make the error go away but I'd prefer to know the reason why it's there in the first place
  • 刚刚澄清了一点措辞。
  • 难道不是因为你在StringProp类上有多重继承,它同时继承了BaseProp和IProp的虚方法?

标签: c++ qt interface


【解决方案1】:

乍一看,好像很经典diamond problem or diamond inheritance

String property 继承自BasePropertyIProperty,并且它们都具有相同的基类IBaseProperty。这就是为什么会有歧义。

【讨论】:

  • 啊哈,太棒了 - 我认为问题在于 IProperty 是从 IBaseProperty 继承的,而这并不是严格要求的。德普。谢谢。
  • @x6herbius 为什么没有严格要求?如果不继承,您可以单独使用 IProperty 吗?在我看来,IProperty 是一个 IBaseProperty。所以它应该继承自它。
【解决方案2】:

问题是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; /*...*/ };

推荐阅读:C++ FAQ 25.8 through 25.15.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多