2009-07-06 10 views
2

構成から異なるクラスの作成を制御することはできますか?設定で制御可能な異なるクラスの作成を可能にすることはできますか?

言って、私はハードコーディングされてこれを行う機能を持っている:

BaseClass* getClassObject(int type) 
{ 
    switch (type) 
    { 
    case 1: 
     return new DerivedClass1(); 
    case 2: 
     return new DerivedClass2(); 
    default: 
     return 0; 
    } 
} 

は、ユーザーが単にデータを記入する必要がありますように、データ構造のいくつかの種類に制御を転送することが可能です関数の振る舞いを制御する構造体?

+1

おそらくあなたは少し質問を明確にすることができます。 switch文の問題は何ですか?コンパイル時に型を知る必要があるという事実?整数(クラス名の文字列)とは違うものを渡したいのですか? –

答えて

0

私はC++の教祖ではありません - 私はDelphi/C#の背景から来ています。 DelphiやC#では、リフレクションを使用して、可能なクラスのリストを動的に作成し、いくつかの設定ファイルで設定されたクラスを選択します。しかし、これがC++でも可能かどうかは分かりません。

+0

C++では、あなたが話している種類のリフレクションをサポートしていません。 –

+0

さて、それは残念です;-)有用な返信のリストから私の答えを取り出してください... –

+0

または、マークをつけ始める前に削除することができます;) –

1

C++では、コンパイル時にすべての型の名前を知っている必要があります。ユーザーが実行時にクラスを作成することを許可することはできません。しかし、あなたが投稿した機能は動作します - 設定ファイルには、DerivedClass1またはDerivedClass2を作成するための整数が含まれています。これを読み取ってスイッチの実行に使用します。

+0

はい、あなたは正しいです。値「タイプ」自体は、構成データ構造/ファイルから導き出すことができる。 – Andy

1

Factory method patternが役に立ちます。

+0

Er、私の質問の関数は工場のパターンです!私は具体的にすべてを書き留めることを伴わない方法があるかどうかを見極めようとしています。 – Andy

+0

それは工場の模様のように見えました。そのパターンがおなじみだったかどうかは分かりませんでした。 –

+0

心配はいりません。私はあなたが今何を意味するのか知っていればいいと思う – Andy

2

C++で述べたように、実行時にクラスを作成することはできません。

あなたの質問を正しく理解していないかもしれませんが、ユーザーが提供するデータで関数/オブジェクトの動作が異なるようにしたい場合は、必要に応じて以下のいずれかを試してみてください。

1]あなたのコードの中で述べたように、あなたが

または

2]あなたはFactoryパターンを使用することができますが必要に作成するために、いずれかのスイッチまたは条件文を使用することができます(ユーザー提供されたデータに異なった機能を動作するように)スニペットオブジェクトタイプ(ユーザ提供データごとに異なるオブジェクトを作成するために、このオブジェクトは異なる挙動を生成するためのコードで交換可能に共通の基底クラスを持つことができる)

又は

3]あなたが櫛を使用することができ のa)作成者関数 b)継承およびインターフェイス c)および動的ライブラリのロード 実行時に適切なタイプのオブジェクトを作成してロードします。 (実行時に指定されたユーザーデータごとに特定のオブジェクトまたは関数のみを読み込む)

+0

お返事ありがとうございます。私は実行時にクラスを発明することには興味がありません。私は、コードをより編集可能にする方法に興味を持っています(コードは実存可能なクラスのみで動作します)。 – Andy

+0

さらにもう1つの方法は、c/C++とともにスクリプト機能を使用することです。 スクリプトの組み込みに必要な努力がそれを正当化するか、または過剰なものになるかどうかはわかりません。 1] TCLのような言語をc/C++と併用することができます。これはC言語ではほとんど使用できません。 または 2]制限付き機能のスクリプト言語を作成できます。 fistアプローチは、TCLに対する外部依存関係を作成しますが、パーサーと制御文を提供することを避けます。 機能が制限され、将来的にはあまり拡張する必要がなくなるまで、2番目は良いことです。 – nurxb01

1

質問に記載されている情報から、C++依存性注入の読み方や使用を検討することをお勧めします。コンテナ。

これはあなたの要件には少し重いかもしれませんが、それは質問から分かりにくいです。 FYI、Dependency injection(http://martinfowler.com/articles/injection.html)は、Martin Fowlerによって作成された用語で、より具体的なInversion of Control(私はあなたに両方のトピックをさらに研究させていただきます)です。

私は個人的には、構成ファイルを介して要求されたオブジェクトの実行時構築を可能にするC#/ .NET依存性注入コンテナであるCastle Windsorを使用しました。

Wikipedia(http://en.wikipedia.org/wiki/Dependency_injection#Existing_frameworks)にC++依存性注入コンテナのリストがあります。私はC++を実行してから数年が経ちましたので、もっと詳しく説明することはできません。

1

もう1つの選択肢は、BaseClassへのインターフェイスの一部がclone()関数であるプロトタイプパターンを使用することです。次に、プロトタイプインスタンスの配列を作成し、そのオブジェクトに対してクローンを呼び出して新しいオブジェクトを取得します。これは、値が異なるインスタンスだけでなく、動作が異なるインスタンスを作成したい場合に便利です。ファクトリメソッドを作成するよりも作業が少なくなることがよくあります。

class BaseClass 
{ 
public: 
    virtual BaseClass* clone() const = 0; 
    virtual ~BaseClass() { } 
    virtual void write() const = 0; 
}; 

template <class C> 
class Cloneable : public BaseClass 
{ 
public: 
    virtual BaseClass* clone() const { 
     return new C (*static_cast<const C*> (this)); 
    } 
}; 

class TypeA : public Cloneable<TypeA> 
{ 
    int value; 

public: 
    TypeA (int value) : value (value) { } 

    virtual void write() const { 
     std::cout << "TypeA (" << value << ") @ " << (void*) this << std::endl; 
    } 
}; 

class TypeB : public Cloneable<TypeB> 
{ 
public: 
    TypeB() { } 

    virtual void write() const { 
     std::cout << "TypeB @ " << (void*) this << std::endl; 
    } 
}; 



int main (int argc, char* argv[]) 
{ 
    std::vector<BaseClass*> prototypes; 

    prototypes.push_back (new TypeA (1)); 
    prototypes.push_back (new TypeA (2)); 
    prototypes.push_back (new TypeB); 

    // create some objects 
    std::vector<BaseClass*> instances; 

    for (size_t i (0); i < 8; ++i) 
     instances.push_back (prototypes [ i % 3 ] -> clone()); 

    for (size_t i (0); i < 8; ++i) 
     instances[ i ] -> write(); 

    // todo: delete everything 
} 
関連する問題