3

1 つの基本クラスから派生する3 つのクラス、、Bがあります。CDA

class A
{
// body
};

class B : public A
{
// body
};

class C : public A
{
// body
};

class D : public A
{
// body
};

B特定の型 ( 、Cまたは) のオブジェクトを作成し、それをクラスDへのポインターとして返すことができるファクトリ関数を作成したいと考えています。A

typedef std::shared_ptr<A> a_ptr;

a_ptr createObject(int type)
{
    switch(type)
    {
    case 0:
        return a_ptr(new B());
    break;
    case 1:
        return a_ptr(new C());
    break;
    case 2:
        return a_ptr(new D());
    break;
    }
}

そして、たとえば type のポインターがある場合、ファクトリによって作成されたオブジェクトをそれBに割り当てたいと思います。B私の頭に浮かんだ唯一の合理的な解決策は次のとおりです。

std::shared_ptr<B> b = std::shared_ptr<B>(dynamic_cast<B*>(createObject(0)));

しかし、それは醜く見えます。そのためのより良い解決策はありますか?または、関数でオブジェクトを作成する別の方法を試す必要がありますか?

4

2 に答える 2

5

のランタイム ダウンキャストを実行する場合はshared_ptr、代わりに次を使用しますstd::dynamic_pointer_cast<>

std::shared_ptr<B> b = std::dynamic_pointer_cast<B>(createObject(0));

作成するオブジェクトの型が実行時に決定され、返されたオブジェクトが型を持つかどうかを確認しようとBしている場合、動的ダウンキャストよりも優れた代替手段はありません。

一方、指定されたオブジェクトのタイプが であることが 100% 確実にわかっBている場合は、次のように使用できますstd::static_pointer_cast<>

std::shared_ptr<B> b = std::static_pointer_cast<B>(createObject(0));

しかし、100% 確実にこれを知った瞬間に、なぜそのような命令が次のようになってはいけないのか、私にはわかりません。

std::shared_ptr<B> b = std::make_shared<B>();
于 2013-03-07T13:17:09.213 に答える
1

少数の「タイプ」の場合、createObject はそれほど悪くはありません。多くの「タイプ」がある場合にのみ醜くなります。次に、それぞれのクラスのファクトリ関数にタイプをマッピングするテーブルを作成することで、より良い結果が得られる可能性があります。例えば:

std::map<int, std::function <a_ptr ()> > dispatcherTable = 
{
    {0, createB },
    {1, createC },
    {2, createD }
};

次に、「タイプ」をテーブルへのインデックスとして使用できます。

new_a = dispatcherTable[a]();

これらの「createB」、「createC」などは、ファクトリ クラスの静的メンバーまたは B、C などのクラスの静的メンバーである可能性があります。好きなように。

于 2013-03-07T13:21:42.517 に答える