2009-08-28 20 views
2

私はこのような仮想クラスたい:各派生した構成は、各クラスがimplmentする必要があるので、これが失敗したEPromptIds仮想データ型/列挙型

class Configuration1 : public Configuration 
{ 
public: 
    enum EPromptId{ 
     epid_HappyBirthday 
    }; 

    CString getPrompt(EPromptId promptId){ 
     return ""; 
    } 
private: 
}; 

class Configuration2 : public Configuration 
{ 
public: 
    enum EPromptId{ 
     epid_JummpingJehoshaphat 
    }; 

    CString getPrompt(EPromptId promptId){ 
     return ""; 
    } 
private: 
}; 

の独自のセットを持つことができるように

class Configuration 
{ 
public: 
    enum EPromptId; 

    virtual CString getPrompt(EPromptId promptId) = 0; 
private: 
}; 

をConfiguration :: EPromptIdパラメータを持つ仮想関数(このコードのようにConfiguration1 :: EPromptIdまたはConfiguration2 :: EPromptIdではなく)。

基本クラスにパラメータ型を認識させることはできますが、派生クラスごとに異なる値を定義することは可能ですか(enumを使用せず、int型を使用しない強く型付けしたままにしておくなど)。

EDIT:2つの異なる「アプリケーション」に対して2つの異なる構成が必要です。プロンプトはdbテーブルに保持できますが、各アプリケーションはそれ自身のテーブルを持ちます。基本構成クラスへのポインタは、あるハードウェアとインターフェースするクラス(実際の表示を行うクラス)に含まれています。ハードウェアは、ユーザー入力を要求および受信するために使用できるI/Oデバイスです。ハードウェアクラスが作成されると、正しい構成クラスへのポインタが渡され、要求されたときに適切なプロンプトが表示されます。

+0

これは 'enum'する必要もありません....とにかく合格するかを知るために自分のタイプを知っておく必要があるだろうから? 'const int'もOKでしょうか? – sbi

+0

列挙型にする必要があります。 – Patrick

答えて

3

最初に:抽象クラスが必要です。 (。。抽象クラスは、少なくとも一つの純粋仮想機能を有するものである仮想基底クラスから派生virtualのクラスである)

その後:いいえ、何がしたいことはできません。 enumを転送宣言することはできず、後で定義することもできます。そして、あなたができる場合でも、誰かがをConfiguration2に渡すとどうなりますか?

は、私はあなたが私たちに説明勧めします(代わりに、あなたはこれを行う方法をを見つけたと思った方法が動作するかどうかの)やって、多分誰かがあなたの問題を解決するためのイディオムを思い付くことができますしたいものを

+0

edit – Patrick

+0

を参照してください。epid_HappyBirthdayをConfiguration2に渡すことはバグで、単純で簡単です。 – Patrick

1

コンパイル時の型チェックとランタイム仮想関数の解決を混在させることはできません。

あなたは、一般的な

class Configuration 
{ 
public: 
    virtual CString getPrompt(int promptId) = 0; 
private: 
}; 

を持っており、デリバティブの2つのメンバ関数を定義することができます:あなたは、有効なpromptIdを確保したい場合は、子クラスで実行時に手動でチェックする必要があります

class Configuration1 : public Configuration 
{ 
public: 
    enum EPromptId{ 
     epid_HappyBirthday 
    }; 

    CString getConfiguration1Prompt(EPromptId promptId){ 
     return ""; 
    } 
    virtual CString getPrompt(int promptId) 
    { 
     return getConfiguration1Prompt(static_cast<EPromptId>(promptId)); 
    } 
private: 
}; 

class Configuration2 : public Configuration 
{ 
public: 
    enum EPromptId{ 
     epid_JummpingJehoshaphat 
    }; 

    CString getConfiguration2Prompt(EPromptId promptId){ 
     return ""; 
    } 
    virtual CString getPrompt(int promptId) 
    { 
     return getConfiguration2Prompt(static_cast<EPromptId>(promptId)); 
    } 
private: 
}; 

を。

このアプローチは有用ではありません。汎用getPrompt()関数を使用するには、EPromptIdにアクセスするために使用する子クラスを知る必要があるからです。

+0

このサンプルでは、​​epid_HappyBirthdayとepid_JummpingJehoshaphatはおそらく同じ値(0)を持つことに注意してください。むしろ、派生クラスで使用されるenumのすべての値を含む、基本クラスに別々の列挙型を作成する必要があります。それは非常にオブジェクト指向ではないが、その唯一の方法は、私はそのような問題を解決するために知っている。 –

+0

getPromptは純粋なバーチャルなので、実行時に呼び出される子クラスは常にわかります – Patrick

+0

@ StefanWoe、それらは間違いなく同じ値を持っています。 – Patrick

0

私のC++は少し錆びですが、あなただけとint型のコンストラクタを追加し、手動で各IDを制御したい場合は、
EPromptId(int型のID)MID(IDを

struct EPromptId { 
    EPromptId() mId(sId++) { } 
    operator int() { return mId; } 
    friend static bool operator==(EPromptId lhs, EPromptId rhs) { 
     return lhs.mId == rhs.mId; 
    } 
private: 
    int mId; 
    static int sId; 
}; 

struct configuration1 { 
    static const EPromptId epid_HappyBirthday; 
    static const EPromptId epid_xxx; 

    CString getPrompt(EPromptId promptId){ 
     if (promptId == epid_HappyBirthday) 
      return ""; 
     else if (promptId == epid_xxx) 
    } 
} 

// somewhere else 
EPromptId configuration1::epid_HappyBirthday; 
EPromptId configuration1::epid_xxx; 

ような何かを行うことはできません){}

とあなたがテンプレートであなたが望むもののほとんどを得ることができるかもしれない

EPromptId configuration1::epid_HappyBirthday = 1; 
EPromptId configuration1::epid_xxx = 5; 
+0

私はこれが何らかの使用を持っているとは思わない。静的変数は、すべての派生クラスに対して1回だけ存在し、コンストラクターが呼び出されるたびにインクリメントされます。 –

+0

初期設定を忘れてマニュアル番号を追加しました – adrianm

3

に初期設定を変更... LONなどあなたはConfiguration*のコレクションを持ち続けることを望んでいなかったので、そうした方法でアクセスできます(あなたはそうでしたか?あなたは)

template< typename ENUM_TYPE > 
class Configuration 
{ 
public: 
    virtual CString getPrompt(ENUM_TYPE promptId) = 0; 
private: 
}; 

その後、

enum EPromptId{ 
    epid_HappyBirthday 
}; 

class Configuration1 : public Configuration<EPromptId> 
{ 
public: 
    CString getPrompt(EPromptId promptId){ 
     return ""; 
    } 
private: 
};