2011-09-13 12 views
1

仕様書に従ってプログラムを記述しました。
仕様には約3種類あり、各タイプは1点ごとに異なる処理をします。C++多重条件文 - マージ

今、私の質問は、あなたがなを持っている場合、「1にそれらのすべてをマージする価値ではないでしょう、で、下に示すように、多かれ少なかれコードの可読性のために、私はそれを書かれている意味if enum-type x "

私はすでにそこにあるプログラムがあると信じていますが、この特定の問題のためにGoogleが私を助けてくれませんでした。事前に助けてくれてありがとう。

/* Point 1.15 Filling Customers bdate */ 

if(current.identifier == APPLE){ output.setValue(1.15, additionalObj.some.color)} 
if(current.identifier == PLUM){ output.setValue(1.15, otherObj.another.color) } 
if(current.identifier == GRAPE){ output.setValue(1.15, default::color) } 


/* Point 1.16 Filling Customers cash*/ 

if(current.identifier == APPLE){ do whatever} 
if(current.identifier == PLUM){ do whatever} 
if(current.identifier == GRAPE){ do whatever} 

結果を達成するために:私はあなたを誤解しているかもしれないが、私はまだ読みやすいコード

編集している間私は、自動的に1つの文にそれらをマージすることができます上の

if(current.identifier == APPLE){ output.setValue(1.15, additionalObj.some.color) 
           do whatever 
} 

そしてそう実際には型ではなく、ただString型の識別子とSubObjectを持つObjectなので、多態性は使用できません。私はあなたが私が達成したいものを見ることができるように上記を調整しました。

+5

C++を使用しているので、これを処理するためにポリモーフィズムのようなオブジェクト指向の機能を使用しているのはなぜですか? –

答えて

3

基本多型のアプローチ:その他の

enum Type { tX, tY, tZ}; 

struct Data 
{ 
    Type type; 
    int data_; 
}; 

class Processor 
{ 

public: 

    virtual void fillCustomersBDate(const Data& data) = 0; 
    virtual void fillCustomersCash(const Data& data) = 0; 

}; 

class XProcessor : public Processor 
{ 
    virtual void fillCustomersBDate(const Data& data) { /* X stuff */} 
    virtual void fillCustomersCash(const Data& data) {/* X stuff */} 
}; 
class YProcessor : public Processor 
{ 
    virtual void fillCustomersBDate(const Data& data) {/* Y stuff */} 
    virtual void fillCustomersCash(const Data& data) {/* Y stuff */} 
}; 

void process(const Data& data) 
{ 
    Processor* processor = processorForType(data.type); 
    // Do general stuff 
    processor->fillCustomersBDate(data); 
    // Do general stuff 
    processor->fillCustomersCash(data); 
    // Do general stuff 
    delete processor; 
} 

おそらく、あなたは、基本クラスにメインフローの大半を移動したいです。

+0

あなたのソリューションをありがとう、私の問題は、私はそれぞれの200の関数を作成する必要があるので、私はオブジェクトごとに3種類x 200関数600メソッドを書く必要があります –

+0

@Oliver Stutz。それは多くの方法を作成する明らかに間違っていない。異なる "型"のメソッドが実際に異なっていて、それぞれが "fillCustomersBDate"のような何かを行う場合は、それを行います。メソッド呼び出しで共通のコードがない場合は、いくつかを集計することができます。実装が本当に異なる場合は、他のテンプレートベースのソリューションが存在する可能性があります。私たちはより明確になるためにはもっと実際のコードを見る必要があります。 – Keith

+0

あなたの答えをありがとう、私にとっては、コードがうまくいくことは重要です.600の方法ではそうではありません。もし、(x){これを実行すると、 if(x){do this} if(x){do}}というように。私はあなたがコードを見たいと思っているが、同じ条件文をマージする、単純なことを依頼していることは分かっている。例えば、(x)が1回だけで、この条件をチェックするすべてがマージされてxをチェックするパフォーマンスが安全になる。 –

0

彼らはすべての異なるなら、あなたは以下のように個々のセクションにそれらを分離することができます:

if (type x) 
    processX1v1_thru_1v15(); // will do all steps 1.1 thru 1.16 for type x 
else if (type y) 
    processY1v1_thru_1v15(); // will do all steps 1.1 thru 1.16 for type y 
: : : 
and so on. 

しかし、あなたは、あなたが/クラスごとに異なる「何」を指定することができます多型に見てみたいことがありますタイプ。あなたはすでにそれを理解していない場合は、C++クラスの継承やポリモーフィズムについて

obj.doWhatever1_01(); // calls obj-specific method depending on type. 
obj.doWhatever1_02(); 
: : : 
obj.doWhatever1_16(); 
5

読む:あなただけのようにdomething行うことができます。 C++のこれらの2つの機能は、あなたの問題を解決するためのよりエレガントな方法を提供します。

+0

@(Upvoters):この短い、例のない答えにすべてのアップポケッターに感謝したい。あなたのアップフォースは、「どこでもコメントする」特権を得ています。彼は簡単な例を提供しているので、キースの答えをupvoteしてください。 – ksming

1

これを行うには2つの方法があります。最初は、多相動作(仮想関数または型パラメータ化による)です。 2番目のタイプはswitchです。最初のもののために

、タイプのそれぞれが共通の(おそらく抽象的)基本クラスから継承することができます。

class Base 
{ 
public: 

    virtual void DoSomething() =0; 

}; 

class A : public Base 
{ 
public: 
    void DoSomething() 
    { 
     cout << "I'm doing something from A!" << endl; 
    } 
}; 

class B : public Base 
{ 
public: 
    void DoSomething() 
    { 
     cout << "I'm doing something from B!" << endl; 
    } 
}; 

この方法では、あなたは、単にタイプBase &Base *の変数、または任意のスマートを使用することができますBaseのポインタ(たとえばshared_ptr<Base)を呼び出し、その変数に対してDoSomethingメソッドを呼び出します。 DoSomethingの正しい実装は、変数の実行時の型に基づいて呼び出されます(DoSomethingは仮想メソッドなので)。

類似の動作を達成するもう1つの方法は、テンプレートによるものです。これは、最初の提案と同様の方法で使用されていますが、あなたは、基本クラスを必要としない、および方法は、仮想である必要はない。

class A 
{ 
public: 
    void DoSomething() 
    { 
     cout << "I'm doing something from A!" << endl; 
    } 
}; 

class B 
{ 
public: 
    void DoSomething() 
    { 
     cout << "I'm doing something from B!" << endl; 
    } 
}; 

その後の操作を処理する関数は、このような何かを定義することができます。

template<typename T> 
void PolymorphicDoSomething(T variable) 
{ 
    T.DoSomething(); 
} 

と、このように使用:もちろん

A a; 
PolymorphicDoSomething(a); 

、この例は少し不自然ですが、それは基本的な考え方だ、とsituatioに応じて、非常に便利ですn。

もう1つの可能性は、あなたが今やっていることを本質的にすることですが、いくつかのif文ではなく、switchという単一の文で行います。変数の型がenumまたはintとして格納されている場合は、実行するために効率的にどの操作を決定するためにスイッチを使用することができます。

enum VariableType 
{ 
    TypeA, 
    TypeB, 
    TypeC, 
    // etc. 
}; 

//... 

switch(variable_type) 
{ 
case TypeA: 
    DoSomethingForA(); 
    break; 
case TypeB: 
    DoSomethingForB(); 
    break; 
case TypeC: 
    DoSomethingForC(); 
    break; 
// etc. 
} 

をしかし、私は、これは本当に仮想メソッドを使用するよりも、それ以上有効であろうことを疑います。また、仮想メソッドは管理しやすくなります。機能を拡張するには、別のクラスを宣言するだけで済みます。既に持っているコードはすべてそれに対応できます。スイッチの場合は、変数の型をチェックするたびにcase文を追加する必要があります。だから私は本当にこの場合仮想メソッドに固執します。

+0

効率はまさに私の問題です。私は、より多くのメソッド呼び出しを構築するのではなく、繰り返し制御メカニズムを取り除こうとしています。 (x == true)、do(x == true)なら、x == trueとすべてのサブステートメントを一度、すべてにする必要があります。マージツールを使用すると、コードを自動的に修正して、わかりやすいコードを残すことができます –