2011-01-17 17 views
0

私は解決方法を知らないという単純な問題があります。&は、データ型が問題ではない変数を扱うことに慣れています。私はWindowsタスクスケジューラ&それが持っている何百万ものオブジェクト、ITask ...このITask ...で働いています。実行時に主変数の型が決定される関数

だから私は、パラメータtriggerType(列挙VAR)に応じて&、機能を持って、変数トリガはあなたが見ればうわ、これは、テキストで説明するのは難しいです...タイプITimeTriggerまたはIBootTriggerのどちらかになりますがその下のコードは私の問題が何であるかを見るのが簡単です。以下の私の例を見て、私の問題を理解することが

そのALOT簡単に:

enum meh { I_WANT_A_INT = 50001, I_WANT_A_FLOAT }; 

bool foo(meh triggerType) 
{  
    switch (triggerType) 
    { 
     case I_WANT_A_INT: 
     { 
      int trigger = 10; 
     } 
     break; 
     case I_WANT_A_FLOAT: 
     { 
      float trigger = 10.111; 
     } 
     break; 
     default: 
     { 
      double trigger = 11; 
     } 
     break; 
    } 

    trigger = 5 * trigger ; // Compile error because trigger is not declared 
    cout << trigger << endl; 
} 

私は、私が使用することができます知っているソリューションは、次のとおりです。
- 私は&は(ITimeTriggerのための1つを持っている機能をオーバーロードすることができますint)action & IBootTrigger(float)のための別のもの。これは私が本当にやりたいことではありません。なぜなら、関数が本当に長くて、それらの間にコードを繰り返すことが多いからです。
- ITimeTrigger & IBootTriggerは両方とも同じオブジェクトITriggerから継承しているため、スイッチの外側にトリガvarをITriggerとして宣言し、スイッチ内で必要なオブジェクトにキャストします。これは今でも動作しますが、 この関数を別の種類のタスクをスケジュールするように拡張すると、ITrigger(win32セマンティクス)から継承されないため、このソリューションは動作しません。

変数のトリガー(実行時にデータ型が決定される)を宣言することで、後でその関数でvarを使用することはできますか?

+0

なぜあなたはC++でプログラミングしているときにPythonで考えていますか? [C++の本](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)を入手して、言語内で正しく機能する方法を学ぶことができます。 – GManNickG

答えて

0

これは実際にはC++では意味をなさない。タイプは実行時に決定されます。 operator*などを組み込み型と同じように振る舞うクラスの階層を作成することはできますが、多態的にこれらのプリミティブ型を混在させたいのはなぜですか?

コードの重複がなく異なるタイプの関数の異なるバージョンが必要な場合は、関数テンプレートを使用して調べることをお勧めします。例えば、 http://www.parashift.com/c++-faq-lite/templates.html

+0

私はScheduleTask(triggerType)関数を持っています; triggerTypeに応じて、起動時、特定の時刻、毎週または毎月にトリガするタスクをスケジュールしたいと思います。これらの異なるアクションのそれぞれに対して、それらは異なるトリガーオブジェクト(ITimerTrigger、IBootTrigger)を必要としますが、同じ方法で使用されるので、私は常にtrigger-> put_Delay( "");と言います。どんなタイプであろうと、 – Sascha

+0

@サスカ:ああ、そうです。したがって、サンプルコードのプリミティブ型( 'int'、' float'など)はあなたの実際の問題を実際に表していませんでしたか?代わりに、 'ITimerTrigger'、' IBootTrigger'などがありますか?その場合は、実際の状況に近いコードにするために質問を編集することをお勧めします。 –

+0

申し訳ありませんが、それらは単なる例でした。テンプレートでこれを行う唯一の方法はありますか? – Sascha

7

テンプレートを使用すると、コードの重複を避けることができます。根本的に異なる動作をするようなタイプの場合

// Common code goes here: 
template<typename TriggerType> 
void bar(TriggerType trigger) 
{ 
    trigger *= 5; 
    std::cout << trigger << std::endl; 
} 

// Differing code goes here: 
void foo(meh trigger_type) 
{ 
    switch (trigger_type) { 
    case I_WANT_A_INT: 
     bar(10); // invokes the int version 
     break; 
    case I_WANT_A_FLOAT: 
     bar(10.111f); // invokes the float version; note the use of 'f' 
     break; 
    default: 
     bar(11.0); // invokes the double version; note the use of '.0' and lack of 'f' 
    } 
} 

、あなたもbarのインスタンス化を専門としていることができます。例えば、上記のように書き換えることができます。ところで

0
#include <iostream> 
using namespace std; 

enum meh { i_want_a_int = 50001, i_want_a_float }; 

template< class Number > 
bool bar(Number trigger) 
{ 
    trigger *= 5; 
    cout << trigger << endl; 
    return true; 
} 

bool foo(meh triggerType) 
{  
    switch (triggerType) 
    { 
     case i_want_a_int: 
      return bar<int>(10); 
     case i_want_a_float: 
      return bar<float>(10.111f); 
     default: 
      return bar<double>(11.0); 
    } 
} 

int main() 
{ 
    foo(i_want_a_float); 
} 

、あなたは大幅にマクロのALL_UPPERCASE識別子を確保することによって、不注意によるテキスト置換の可能性を減らすことができます。

乾杯& HTH、

0

テンプレートはおそらくソリューションです。

詳細を見ることなく言わなければならなかったが、「関数は実際にはたくさんの繰り返しコードで長くなっている」と言います。

あなたが持つことができます。

  1. クラステンプレートへの単一の関数テンプレート
  2. リファクタリングを、 、基本クラスのメソッドで非タイプ固有のコードと が働くかもしれないうまく
  3. 機能のコレクション の一部は、 トップレベル関数がテンプレート化されてテンプレート化されています
  4. oveサブルーティンの一部をロードします。

注あなたはまた、型に列挙型からマッピングするためにテンプレートを使用します。

enum meh { I_WANT_A_INT = 50001, I_WANT_A_FLOAT, I_WANT_A_DOUBLE }; 

template<meh = I_WANT_A_DOUBLE> 
struct TriggerType 
{ 
    typedef double Type; 
}; 
template<> 
struct TriggerType<I_WANT_A_INT> 
{ 
    typedef int Type; 
}; 
template<> 
struct TriggerType<I_WANT_A_FLOAT> 
{ 
    typedef float Type; 
}; 

template<class T> void setValue(T& t); 

template<> void setValue<double>(double& t) { t = 11;} 
template<> void setValue<int>(int& t) { t = 10;} 
template<> void setValue<float>(float& t) { t = 10.111f;} 

template<class T> 
bool fooTyped() 
{ 
    T trigger; 
    setValue(trigger); 
    trigger *= 5; 
    std::cout << trigger << std::endl; 
    return true; 
} 

bool foo(meh triggerType) 
{  
    bool ret = false; 
    switch (triggerType) 
    { 
     case I_WANT_A_INT: 
     { 
      ret = fooTyped<TriggerType<I_WANT_A_INT>::Type>(); ; 
     } 
     break; 
     case I_WANT_A_FLOAT: 
     { 
      ret = fooTyped<TriggerType<I_WANT_A_FLOAT>::Type>(); ; 
     } 
     break; 
     default: 
     { 
      ret = fooTyped<TriggerType<I_WANT_A_DOUBLE>::Type>(); ; 
     } 
     break; 
    } 
    return ret; 
}  

void test() 
{ 
    foo(I_WANT_A_INT); 
    foo(I_WANT_A_FLOAT); 
    foo((meh)63); 
} 

注型に列挙型のマッピングに派​​遣。実行時の値を使用してテンプレートをインスタンス化することはできないため、この明示的なボイラープレートが必要です。

関連する問題