修复C++多重继承模糊调用

lar*_*pco 6 c++ virtual-inheritance diamond-problem

我有三个类这样的结构:

#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;
}
Run Code Online (Sandbox Code Playgroud)

我得到以下内容:

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是a CharacterKeywordAddressType一个MeasurementKeyword通过模板化之间描绘AddressType.并在更新的代码中使用它.或者我可以指定我想要的成员的名称空间.由于模板化的方式尚未被提及作为答案,这是一个糟糕的解决方案吗?我应该只指定我想要的成员的名称空间吗?

template <class T>
class AddressType : public T
{

    private:
        float address;
        float addresExt;
};

int main()
{
    AddressType<MeasurementKeyword> *a = new AddressType<MeasurementKeyword>();
    a->GetValue();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

aar*_*man 16

这是因为钻石继承模式,要解决错误,您可以指定您希望该成员的特定命名空间.

paddressType->MeasurementKeyword::GetValue()
Run Code Online (Sandbox Code Playgroud)

要么

paddressType->CharacterKeyword::GetValue()  
Run Code Online (Sandbox Code Playgroud)
  1. 基本上,您的AddressType类可以GetValue从它继承的类中访问成员,也不能选择一个(调用不明确).
  2. 范围解析操作符(::)有助于确定你真正想要哪一个.
  3. 你还没有说过你真正想要这个代码做什么,所以我只是说复杂的继承模式通常不利于创建可读代码,重新考虑你真正想要的东西.


小智 6

像这样定义AddressType:

class AddressType : public CharacterKeyword, public MeasurementKeyword
{
public:
    using MeasurementKeyword::GetValue;
private:
    float address;
    float addresExt;
};
Run Code Online (Sandbox Code Playgroud)


Dim*_*ima 5

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

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

  • virtual 没有解决这个问题,调用还是有歧义的,我同意其余的 (2认同)