2016-12-31 4 views
4

の実装から延びるIは、2つのインターフェースを有する:合わせ界面へのポインタ - クラスをポイントいずれかを実装し、他の

class FirstInterface 
{ 
    virtual int getId() const = 0; 
}; 

class SecondInterface 
{ 
    virtual void setId(int id) = 0; 
}; 

これは複合インタフェースである:

class CombinedInterface : public FirstInterface, public SecondInterface 
{ 

}; 

これを

class FirstConcrete : public FirstInterface 
{ 
    virtual int getId() const 
    { 
     return 1; 
    } 
}; 

ここでは、このクラスCompleteConcreteCombinedInterfaceである必要がありますが、FirstConcreteの実装を同時に再利用したいと考えています。

class CompleteConcrete : public FirstConcrete, public SecondInterface 
{ 
    virtual void setId(int id) { } 
}; 

// This is wrong C++ 
// Cannot convert from CompleteConcrete * to CombinedInterface * 
// CombinedInterface * combinedInterface = new CompleteConcrete(); 

これはもちろん機能しません。 誰でもC++でこの目標を達成する方法を知っていますか?

+0

私は仮想継承を使用してこの作業を行うことができます。また、階層を少し微調整することもできます。残りの部分を仮想継承で動作させることができれば、それは1つの答えになります。仮想継承が何を意味するのかわからない場合は、おそらくこれはうまくいかないでしょう。 –

+0

本当に 'CombinedInterface'が必要ですか? – Jarod42

+1

構成を使用して実装を再利用することができます。 – Jarod42

答えて

1

ここで私はコメントで述べた仮想継承ベースのソリューションです:仮想継承で

class FirstInterface 
{ 
    virtual int getId() const = 0; 
}; 

class SecondInterface 
{ 
    virtual void setId(int id) = 0; 
}; 


class CombinedInterface : virtual public FirstInterface, 
       virtual public SecondInterface 
{ 

}; 

class FirstConcrete : virtual public FirstInterface 
{ 
    virtual int getId() const 
    { 
     return 1; 
    } 
}; 

class CompleteConcrete : virtual public FirstConcrete, 
      virtual public CombinedInterface 
{ 
    virtual void setId(int id) { } 
}; 

void example() 
{ 
    CombinedInterface * combinedInterface = new CompleteConcrete(); 
} 

は、(部屋の中の象のほかに)必要なの唯一の変化はCompleteConcrete乗算を持つことです - SecondInterfaceの代わりにCombinedInterfaceから継承します。このように考えることができます:CompleteConcreateの画像では、SecondInterfaceの追加だけでなく、CombinedInterfaceをサポートするようになりました。

仮想継承を嫌う人もいます。私はしません。それはC++のユニークな機能の1つで、他の高レベル言語を共有するTMKはありません。これは非常に強力なツールであり、他の方法では解決しにくい特定の問題を解決することができます。仮想継承の二つの主な欠点は以下のとおりです。

  1. 、それは非常に強力なので、それは簡単に悪用されると、様々な問題につながることができます。

  2. 仮想継承されたクラスにデフォルト以外のコンストラクタがある場合、事実上継承するすべてのクラスがそれを構築する責任を負うため、すぐに苦労します。

しかし限り、仮想継承が正しく使用され、関与のクラスは自分自身を構築する取ることができますように、仮想継承は便利なツールです。

P.S.私はまた、ちょうど頭に浮かんだもう1つの代替ソリューションについても言及します。 、あなたはそれはのように、いくつかの特定の機能のために必要なことができるだけのように、あなたのCombinedInterfaceを持っていると言う場合:

void somefunction(CombinedInterface &object); 

あなたの機能を組み合わせインターフェースが必要です。

は小さな変更してください:

void somefunction(FirstInterface &first, SecondInterface &second); 

をして、両方のパラメータと同じオブジェクトを渡します。両方のインタフェースを実装するCompleteConcreteに、クラス階層を変更することなく渡すことができます。

template<typename T> void somefunction(T &&t) 
{ 
    real_somefunction(std::forward<T>(t), std::forward<T>(t)); 
} 

void real_somefunction(FirstInterface &first, SecondInterface &second); 

あなたはかなりCombinedInterfaceを取り除くと、単にsomefunction()に両方のインターフェイスを実装する任意のオブジェクトを渡すと、あなたのreal_somefunction()することができます:あなたはまた、機能がまだ一つのパラメータを取るように見えますテンプレートのファサードを持つことができます1つまたは他のパラメータを使用して適切なインタフェースを呼び出します。

両方のインターフェイスを実装するオブジェクトへのポインタを持ち歩く必要があるとします。

class combined_pointer : public std::pair<FirstInterface *, SecondInterface *> { 

public: 
    template<typename T> combined_pointer(T *t) 
      : std::pair<FirstInterface *, SecondInterface *>(t, t) 
    {} 
}; 

ちょうど出発点。

+0

他のソリューションの説明と紹介。なぜ私が実際にCombinedInterfaceが必要なのかを教えてください。私は、CombinedInterfaceへのポインタを返すファクトリを実装しています。このため、2つのインターフェイスで再生するというトリックは機能しません。 –

0

私は仮想継承を使用しました。

これは警告とともに正常にコンパイルされましたが、問題はないと思います。

class FirstInterface 
{ 
    virtual int getId() const = 0; 
}; 

class SecondInterface 
{ 
    virtual void setId(int id) = 0; 
}; 

class CombinedInterface : virtual public FirstInterface, public SecondInterface 
{ 

}; 

class FirstConcrete : virtual public FirstInterface 
{ 
    virtual int getId() const 
    { 
     return 1; 
    } 
}; 


class CompleteConcrete : public CombinedInterface, public FirstConcrete 
{ 
    virtual void setId(int id) { } 
}; 


// warning: C4250: inherits via dominance 
CombinedInterface * combinedInterface = new CompleteConcrete(); 
+0

はい、OKです。 C4250の警告を抑止することができます。あなたは優位性を介して継承を望みます。なぜ私はMSコンパイラの開発者がそれが悪いと判断したのか分かりません。 –

関連する問題