我需要编写一个可以创建任何类型对象的函数。它接收类名作为参数。 如果类相似,我们可以从单个基类派生所有这些类,并让函数返回Base *。该函数的用户可以使用运行时多态来使用返回的对象。在这种情况下,功能如下所示。
Base* createObject(string objName)
{
if(objName == "D1")
return new D1;
else if(objName == "D2")
return new D2;
return NULL;
}
如果类不相似,则不能从单个基类继承它们,因为它不是正确的继承。在这种情况下,上述功能将无用。 让我们说我有3个不同的类,如直升机,厨房和学院。 在这种情况下,单个函数如何创建任何类型的对象? 我有一个如下的解决方案。 使用包装类来包装Union中的所有不同类指针。 然后让函数创建Wrapper对象并根据传递给它的classname填充适当的类指针。 那个功能看起来像下面
Wrapper* createObject(string objType)
{
Wrapper *pWrapper = new Wrapper();
pWrapper->objectType = objType;
if(objType == "Helicopter")
{
pWrapper->pHelicopter = new Helicopter;
}
else if(objType == "Kitchen")
{
pWrapper->pKitchen = new Kitchen;
}
else if(objType == "College")
{
pWrapper->pCollege = new College();
}
return pWrapper;
}
Wrapper类如下所示。
class Wrapper
{
public:
string objectType;
union
{
Helicopter *pHelicopter;
Kitchen *pKitchen;
College *pCollege;
};
};
有没有比上面更好的解决方案?
答案 0 :(得分:1)
包装好的想法在我眼里是不行的。它使用户感到困惑的是没有正确使用多态性。我会为每个逻辑组使用create函数,或者使用具有相同基类的所有类。这可能会导致多个创建功能,但在这种情况下,您应该过度思考您的设计。另一种解决方法是将抽象接口类定义为“可创建”或左右,但我也不喜欢它。 ; - )
答案 1 :(得分:0)
如果您愿意使用'枚举'而不是'字符串',这是一个可能的解决方案。它不会避免单一功能,但至少可以摆脱那个巨大的if-else
enum X {HELI, SHIP, BUS, TRAIN, COLLEGE, KITCHEN};
struct Heli{
};
struct College{
};
....
template<X x> struct Creator{
};
template<> struct Creator<HELI>{
Heli *Create(){return new Heli();}
};
template<> struct Creator<COLLEGE>{
College *Create(){return new College();}
};
int main(){
Heli *ph = Creator<HELI>().Create();
College *pc = Creator<COLLEGE>().Create();
delete ph;
delete pc;
}
答案 2 :(得分:0)
Boost已经有两种可能的解决方案:Boost.Variant和Boost.Any。
但是如果可以的话,最好首先避免这样的设计。如果一个函数返回不相关的对象,并且您无法重构为类型提供公共接口,则应该将其拆分为多个函数。