2

構成からさまざまなクラスの作成を制御することはまったく可能ですか?

たとえば、ハードコードされたこれを行う関数があります。

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

ユーザーが関数の動作を制御するためにデータ構造に入力するだけでよいように、制御をある種のデータ構造に転送することは可能ですか?

4

6 に答える 6

2

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

私はあなたの質問を正しく理解していないかもしれませんが、ユーザーが提供したデータに対して関数/オブジェクトの動作を変えたい場合は、必要に応じて次のいずれかを試してください。

1]コード​​スニペットで述べたように、スイッチまたは条件ステートメントのいずれかを使用できます(ユーザーが提供したデータで関数を異なる方法で動作させるには)

また

2] ファクトリ パターンを使用して、必要なオブジェクト タイプを作成できます (ユーザーが提供するデータごとに異なるオブジェクトを作成するには、このオブジェクトに共通の基本クラスを持たせ、コードで置き換えて異なる動作を生成することができます)。

また

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

于 2009-07-06T11:13:41.223 に答える
1

もう 1 つの方法は、インターフェースの一部が関数であるプロトタイプ パターンを使用することBaseClassですclone()。次に、プロトタイプ インスタンスの配列を作成し、それらに対して 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
}
于 2009-07-06T12:16:55.567 に答える
1

C++ では、コンパイル時にすべての型の名前がわかっている必要があります。ユーザーが実行時にクラスを作成することを許可することはできません。ただし、投稿した関数は機能します。構成ファイルには、DerivedClass1 または DerivedClass2 を作成するかどうかを示す整数が含まれます。これは読み取られ、切り替えを実行するために使用されます。

于 2009-07-06T11:01:01.107 に答える
1

Factory method patternが役立つ場合があります。

于 2009-07-06T11:06:54.653 に答える
1

質問で提供された限られた情報から、C++ 依存性注入コンテナーを読んだり、使用を検討したりすることを検討してください。

これは要件に対して少し重いかもしれませんが、質問からそれを判断するのは困難です。参考までに、依存性注入 ( http://martinfowler.com/articles/injection.html ) は、Martin Fowler によって造られた用語であり、より具体的な種類の制御の反転です (両方のトピックをさらに調査することはお任せします)。

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

ウィキペディア ( http://en.wikipedia.org/wiki/Dependency_injection#Existing_frameworks )には、C++ 依存性注入コンテナーのリストがあります。C++ を使用してから数年が経過しているため、それらについて詳しく説明することはできません。

于 2009-07-06T11:57:28.170 に答える
0

私は C++ の第一人者ではありません。Delphi/C# のバックグラウンドを持っています。Delphi または C# では、リフレクションを使用して可能なクラスのリストを動的に作成し、構成ファイルで構成されたクラスを選択します。ただし、これが C++ でも可能かどうかはわかりません。

于 2009-07-06T11:00:43.183 に答える