返回特定类型对象的工厂函数 - 如何以更好的方式执行

时间:2013-03-07 13:09:42

标签: c++ pointers shared-ptr factory

我有3个类BCD,它们派生自一个基类A

class A
{
// body
};

class B : public A
{
// body
};

class C : public A
{
// body
};

class D : public A
{
// body
};

我想创建一个工厂函数,让我创建特定类型的对象(BCD)并将其作为指向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;
    }
}

然后,如果我有一个类型B的指针,我想将工厂创建的B对象分配给它。我想到的唯一合理的解决方案是:

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

但它看起来很难看。那有更好的解决方案吗?或者也许我应该尝试用我的函数创建对象的不同方法?

2 个答案:

答案 0 :(得分: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>();

答案 1 :(得分:1)

对于少量“类型”,您的createObject看起来并不太糟糕。如果有很多“类型”,它只会变得丑陋。然后,通过为相应类的工厂函数创建表映射类型,可以更好。例如:

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

然后你可以使用'type'作为表格的索引:

new_a = dispatcherTable[a]();

那些“createB”,“createC”等可以是工厂类的静态成员,也可以是B,C等静态成员。你想要它的任何方式。