2011-01-04 10 views
2

C++では、同じことを計算するさまざまな方法を表すいくつかのアルゴリズムを実装する必要があります。OOを使用して一般的にパラメータを表す方法は?

さまざまなアルゴリズムを表すためにインターフェイスを使用することを考えました。

class AlgorithmInterface 
{ 
    public: 
    virtual double ComputeSomething(void* parameter) = 0; 
} 

class AlgorithmImplementation1: public AlgorithmInterface 
{ 
    public: 
    virtual double ComputeSomething(void* parameter) { /* implementation */} 
} 

class AlgorithmImplementation2: public AlgorithmInterface 
{ 
    public: 
    virtual double ComputeSomething(void* parameter) { /* implementation */} 
} 

これらのそれぞれのパラメータ(前の例でのvoid *)が異なっているが、どのように私は一般的にそれらを表すことができますか?

この例では、これを表現する方法がわからないため、私はvoid *を使用しました。どのようにすればいいのか教えてください:パラメータの継承を継承してキャストする必要がありますか?

+1

問題は、インタフェースが全く異なる場合、同じ階層に属しているかどうかです。すなわち、呼び出しコードは異なる実装*を使用することはできませんが、一般には*どの実装を呼び出すかを知る必要があります。アルゴリズムに渡すことができます。異なるインタフェースを持つ場合、なぜそれらはすべて 'AlgorithmInterface'ですか? –

+0

デビッド、私はたいていその場でswitch文を避けたいと思っていました。 – BlueTrin

+0

あなたはコメントの返信で人に正しく@アドレスを付ける必要があります。そうしないと、返信は返信タブに表示されません。 – sbi

答えて

1

古典的なOO(ランタイム)多相を使用している場合、パラメータは、派生クラスオブジェクトを渡すことができる基本クラスのポインタ/参照である必要があります。 STLが行うように、テンプレートとコンパイル時の多型に変換し、アルゴリズムとパラメータをテンプレートパラメータのインスタンスとして渡します。テンプレートと

、これはあなたのコードがどのように見えるかです:することができます、その後、計算は同じままで、単にパラメータの型が異なる場合

class AlgorithmImplementation1 
{ 
    public: 
    virtual double ComputeSomething(Param1* parameter) const 
    { /* implementation */} 
} 

class AlgorithmImplementation1 
{ 
    public: 
    virtual double ComputeSomething(Param2* parameter) const 
    { /* implementation */} 
} 

template< typename Algorithm > 
void use_algorithm(const Algorithm& algorithm) 
{ 
    // ... 
    // get_parameter() _must_ return whatever the algorithm takes 
    double d = algorithm(get_parameter()); 
    // ... 
} 

Param1 get_parameter(); 

void f() 
{ 
    use_algorithm(AlgorithmImplementation1()); 
} 
(あなたの質問の私の理解に基づいて)
+0

Liakとsbi、私はテンプレートに関してはあまり経験がありませんし、継承と組み合わせなければならない場合は、いくつかの例へのリンクがありますか? – BlueTrin

+1

@BlueTrin:完了。それは役に立ちますか? – sbi

+0

あなたのソリューションとMartin Yorkソリューションを試してみましょう。誰もあなたの解決策を投票しなかった理由は分かりません(私以外)。 – BlueTrin

9

コンストラクタでパラメータを渡すことができます。
さらに、仮想メンバーをプライベートにしてオブジェクトファンクタます

class AlgorithmInterface 
{ 
    public: 
    double operator()() {return this->ComputeSomething();} 
    private: 
    virtual double ComputeSomething() = 0; 
} 

class AlgorithmImplementation1: public AlgorithmInterface 
{ 
    virtual double ComputeSomething() { /* implementation */} 
    public: 
     AlgorithmImplementation1(Parameter 1); 
} 

class AlgorithmImplementation2: public AlgorithmInterface 
{ 
    virtual double ComputeSomething() { /* implementation */} 
    public: 
     AlgorithmImplementation2(Item a1,Item a2); 
} 

int main() 
{ 
    AlgorithmImplementation2 job(Item(12), Iterm(13)); 

    double result = job(); // execute; 
} 
+0

これは有効ですが、実装固有のインスタンスをユニークにしたいと思っていました。私は彼らをシングルトンに入れようとしていました。この理由は、メソッドのグローバル設定ではなく、パラメータがメソッドのパラメータのほうが多いためです。 – BlueTrin

+0

+1:オリジナルの問題を賢明なものに変換しました - 質問コードで、 'AlgorithmInterface'はインターフェースを定義しません。* NVIを使って*インプリメンテーションインターフェースから*ユーザーインターフェースを分離しました* --what' AlgorithmInterfaceユーザーに、実装から必要なものを提供します。 –

+1

@BlueTrin:あなたのパラメータへの参照だけを登録すると、 'AlgorithmImpl'オブジェクトは軽量になります。あなたは確かにそれをシングルトンにすることから何も得られません。 –

0

をあなた本当に継承を必要ですか?その場合、関数のテンプレートはオプションになりません(少なくとも現在の標準では仮想関数テンプレートを使用できません)。そしてMartinのソリューションが動作します。あなたが継承を必要としない場合はもちろんの下に十分なはず

class AlgorithmImplementation1 
{ 
    public: 
    template <typename ParamType> 
     double ComputeSomething(ParamType const& parameter) { /* implementation */} 
} 

class AlgorithmImplementation2 
{ 
    public: 
    template <typename ParamType> 
     double ComputeSomething(ParamType const& parameter) { /* implementation */} 
} 

これは、あなたがparameterを使用する予定の方法に依存し、そして、あなたは(たとえば、stringに異なるintを扱う)オーバーロードを使用したほうが良いかもしれ、 parameterに一貫したインターフェイスがある場合は、関数テンプレートで十分です。

1

もう1つの可能性は、アルゴリズムに「パラメータストリーム」を渡すことです。アルゴリズムは、ParameterStreamを参照することができます。

次に、導出されたアルゴリズムは、適切なタイプ(数)のパラメータをストリームから適宜抽出します。ストリームは、パラメータのタイプセーフな抽出(デシリアライゼーション)を実装し、(必要に応じて)バージョン管理を実装することもできます。

この可能性があるIMHOでは、今後異なるアルゴリズムで異なる数のパラメータが必要になっても、インターフェイスを不変に保つことができるという利点があります。

基本的に、必要なパラメータのシリアル化された形式を含むパラメータを送信し、アルゴリズムの実装で必要に応じて非直列化/検証します。

コンパイル時に明確にカットされているテンプレートは、以前のポスターで述べたようにテンプレートとしても使用できます。