7

我有三个这样的类:

#include <iostream>
using namespace std;

class Keyword
{
    public:
        virtual float GetValue() = 0;
};

class CharacterKeyword : public Keyword
{
    public:
        virtual float GetValue(){return _value;}
    private:
        float _value;
};

class MeasurementKeyword : public Keyword
{
    public:
        virtual float GetValue(){return _value;}
    private:
        float _value;
};

class AddressType : public CharacterKeyword, public MeasurementKeyword
{

    private:
        float address;
        float addresExt;
};

int main()
{
    AddressType *a = new AddressType();
    a->GetValue();
    return 0;
}

我得到以下信息:

In function ‘int main()’:
error: request for member ‘GetValue’ is ambiguous
error: candidates are: virtual float Keyword::GetValue()
error: virtual float MeasurementKeyword::GetValue()
error: virtual float CharacterKeyword::GetValue()

我对多重继承做了一些阅读,我知道它有很多陷阱——这就是其中之一。我需要我的类结构是这样的,所以我想知道是否有一种方法可以使用模板来解决这个问题?

更新
阅读您的评论后,我最初的想法是,也许我AddressType可以CharacterKeyword通过AddressType模板MeasurementKeywordAddressType. 并在更新的代码中使用它。或者我可以只指定我想要的成员的命名空间。由于尚未提及模板化方式作为答案,这是一个不好的解决方法吗?我应该只指定我想要的成员的命名空间吗?

template <class T>
class AddressType : public T
{

    private:
        float address;
        float addresExt;
};

int main()
{
    AddressType<MeasurementKeyword> *a = new AddressType<MeasurementKeyword>();
    a->GetValue();
    return 0;
}
4

3 回答 3

16

这是因为菱形继承模式,要解决错误,您可以指定您希望成员喜欢的特定命名空间。

paddressType->MeasurementKeyword::GetValue()

或者

paddressType->CharacterKeyword::GetValue()  

  1. 基本上,您的AddressType类可以访问GetValue它所继承的两个类的成员,并且不能选择一个(调用不明确)。
  2. 范围解析运算符 ( ::)有助于指定您真正想要的。
  3. 你还没有说你真正想要这个代码做什么,所以我只会说通常复杂的继承模式不利于创建可读的代码,重新考虑你真正想要的。
于 2013-08-10T02:26:52.473 回答
7

像这样定义地址类型:

class AddressType : public CharacterKeyword, public MeasurementKeyword
{
public:
    using MeasurementKeyword::GetValue;
private:
    float address;
    float addresExt;
};
于 2013-08-10T02:40:17.177 回答
5

通常,当您遇到致命的死亡钻石时,这表明您应该重新考虑您的设计。但是,如果您绝对无法避免这种情况,C++ 以虚拟继承的形式提供了解决方案。虚拟继承解决了一些“钻石歧义”,但它也很笨重。例如,您必须在派生类的构造函数中显式调用父类的非默认构造函数。

再一次,最好的方法是首先避免钻石。我已经用 C++ 编程很多年了,到目前为止,我的代码中从来没有遇到过这个问题。

于 2013-08-10T02:31:17.603 回答