7

次のような構造の 3 つのクラスがあります。

#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()

私は多重継承についていくつか読んだことがありますが、それには多くの落とし穴があることを知っています - これはそのうちの1つです。クラス構造をこのようにする必要があるので、テンプレートを使用してこれを修正できる方法があるかどうか疑問に思っていましたか?

更新
あなたのコメントを読んだ後、私の最初の考えAddressTypeCharacterKeyword、. そして、更新されたコードでそれをそのまま使用します。または、必要なメンバーの名前空間を指定することもできます。テンプレート化された方法はまだ答えとして言及されていないので、それは悪い修正ですか? 必要なメンバーの名前空間を指定するだけでよいですか?AddressTypeMeasurementKeywordAddressType

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 に答える
5

一般的に、致命的なダイアモンド オブ デスに出くわしたときは、デザインを再考する必要があるというサインです。ただし、この状況をどうしても回避できない場合は、C++ が仮想継承という形で解決策を提供します。仮想継承は「ダイアモンドのあいまいさ」の一部を解決しますが、扱いにくいものでもあります。たとえば、派生クラスのコンストラクターで、親の既定以外のコンストラクターを明示的に呼び出す必要があります。

繰り返しますが、最善の方法は、最初からダイヤモンドを避けることです。私は長年 C++ でプログラミングを行ってきましたが、これまでコードでこの問題が発生したことはありません。

于 2013-08-10T02:31:17.603 に答える