如何根据classname参数编写单个函数来为不同类创建不同的对象?

时间:2010-08-21 09:13:49

标签: c++

我需要编写一个可以创建任何类型对象的函数。它接收类名作为参数。 如果类相似,我们可以从单个基类派生所有这些类,并让函数返回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;
    };
};

有没有比上面更好的解决方案?

3 个答案:

答案 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.VariantBoost.Any

但是如果可以的话,最好首先避免这样的设计。如果一个函数返回不相关的对象,并且您无法重构为类型提供公共接口,则应该将其拆分为多个函数。