我有3个类B
,C
,D
,它们派生自一个基类A
:
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;
}
}
然后,如果我有一个类型B
的指针,我想将工厂创建的B
对象分配给它。我想到的唯一合理的解决方案是:
std::shared_ptr<B> b = std::shared_ptr<B>(dynamic_cast<B*>(createObject(0)));
但它看起来很难看。那有更好的解决方案吗?或者也许我应该尝试用我的函数创建对象的不同方法?
答案 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等静态成员。你想要它的任何方式。