3

我有 3 个类,,,,B派生自一个基类:CDA

class A
{
// body
};

class B : public A
{
// body
};

class C : public A
{
// body
};

class D : public A
{
// body
};

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

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

4

2 回答 2

5

如果要执行 a 的运行时向下转换shared_ptr,请使用std::dynamic_pointer_cast<>

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

如果要创建的对象的类型是在运行时确定的,并且您尝试检查返回的对象是否具有 type B,那么我看不到比动态向下转换更好的选择。

另一方面,如果您100%确定指向的对象具有 type 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 回答