C++ 如何有条件地实例化不同的父/子类?

C++ 如何有条件地实例化不同的父/子类?,c++,class,oop,inheritance,C++,Class,Oop,Inheritance,类似的问题被张贴和回答,但提议的解决方案不适合我 我有三个具有多级继承的类: class Model { public: Model(); template <typename InputModelType> void importModel(const InputModelType &m); virtual void process(); }; class SpecialModel : public Model { public:

类似的问题被张贴和回答,但提议的解决方案不适合我

我有三个具有多级继承的类:

class Model
{
public:
    Model();
    template <typename InputModelType>
    void importModel(const InputModelType &m);
    virtual void process(); 
};

class SpecialModel : public Model
{
public:
    SpecialModel();
    template <typename InputModelType>
    void importSpecialModel(const InputModelType &m);
    virtual void process() override; 
};

class SpecialSpecialModel : public SpecialModel
{
public:
    SpecialModel();
    template <typename InputModelType>
    void importSpecialSpecialModel(const InputModelType &m);
    virtual void process() override; 
};
使用上述代码,我得到以下错误:

“类模型”没有名为“importSpecialModel”的成员

“类模型”没有名为“importSpecialSpecialModel”的成员


问题在于,导入函数是模板化的,因此在基类中将它们定义为虚拟函数,然后在子类中重写是无效的。

只能使用对象静态类型的函数。 可以使用派生类型执行以下操作

std::unique_ptr<Model> CreateModel(int model_type, const InputModelType &m)
{
    switch(model_type)
    {
        case 1:
        {
            auto model = std::make_unique<PairwiseMRF>();
            model->importSpecialModel(gm);
            return model; // or std::move(model)
        }
        case 2:
        {
            auto model = std::make_unique<PairwiseMetricMRF>();
            model->importSpecialSpecialModel(gm);
            return model; // or std::move(model)
        }
        default:
        {
            auto model = std::make_unique<Model>();
            model->importModel(gm);
            return model;
        }
    }
}

只能从对象的静态类型使用函数。 可以使用派生类型执行以下操作

std::unique_ptr<Model> CreateModel(int model_type, const InputModelType &m)
{
    switch(model_type)
    {
        case 1:
        {
            auto model = std::make_unique<PairwiseMRF>();
            model->importSpecialModel(gm);
            return model; // or std::move(model)
        }
        case 2:
        {
            auto model = std::make_unique<PairwiseMetricMRF>();
            model->importSpecialSpecialModel(gm);
            return model; // or std::move(model)
        }
        default:
        {
            auto model = std::make_unique<Model>();
            model->importModel(gm);
            return model;
        }
    }
}
这是一个变体。通过使用函数指针映射,可以避免使用
switch
语句

// Independent functions to import the various model types

std::unique_ptr<Model> importPairwiseMRF(GmType gm)
{
   auto model = std::make_unique<PairwiseMRF>();
   model->importSpecialModel(gm);
   return model;
}

std::unique_ptr<Model> importPairwiseMetricMRF(GmType gm)
{
   auto model = std::make_unique<PairwiseMetricMRF>();
   model->importSpecialSpecialModel(gm);
   return model;
}

std::unique_ptr<Model> importModel(GmType gm)
{
   auto model = std::make_unique<Model>();
   model->importModel(gm);
   return model;
}

// Function to import a model given a model_type and the import data.
std::unique_ptr<Model> importModel(int model_type, GmType gm)
{
   // Define a function type that can take gm and return a Model*
   typedef = std::unique_ptr<Model> (*Function)(GmType gm);

   // Create a map of the functions known so far.
   std::map<int, Function> theMap =
   {
      {1, importPairwiseMRF},
      {2, importPairwiseMetricMRF},
      {3, importModel}
   };

   // If there is a function for the given model_type, use it.
   // Otherwise, return nullptr.
   if ( theMap[model_type] != nullptr )
   {
      return theMap[model_type].second(gm);
   }
   else
   {
      return {};
   }
}
这是一个变体。通过使用函数指针映射,可以避免使用
switch
语句

// Independent functions to import the various model types

std::unique_ptr<Model> importPairwiseMRF(GmType gm)
{
   auto model = std::make_unique<PairwiseMRF>();
   model->importSpecialModel(gm);
   return model;
}

std::unique_ptr<Model> importPairwiseMetricMRF(GmType gm)
{
   auto model = std::make_unique<PairwiseMetricMRF>();
   model->importSpecialSpecialModel(gm);
   return model;
}

std::unique_ptr<Model> importModel(GmType gm)
{
   auto model = std::make_unique<Model>();
   model->importModel(gm);
   return model;
}

// Function to import a model given a model_type and the import data.
std::unique_ptr<Model> importModel(int model_type, GmType gm)
{
   // Define a function type that can take gm and return a Model*
   typedef = std::unique_ptr<Model> (*Function)(GmType gm);

   // Create a map of the functions known so far.
   std::map<int, Function> theMap =
   {
      {1, importPairwiseMRF},
      {2, importPairwiseMetricMRF},
      {3, importModel}
   };

   // If there is a function for the given model_type, use it.
   // Otherwise, return nullptr.
   if ( theMap[model_type] != nullptr )
   {
      return theMap[model_type].second(gm);
   }
   else
   {
      return {};
   }
}

@RSahu:
process()
似乎不是模型创建的一部分,这就是我省略它的原因。我添加的用例更类似于OP的代码。谢谢你的快速回答!我一提交问题就看到了,但我花了一些时间来测试。它起作用了!但似乎std::make_unique只是C++14,不是吗?我必须使用C++14进行编译。有没有办法让它在C++11中工作?您仍然可以实现自己的
make_unique
或将
unique_ptr
构造函数与new一起使用。谢谢。顺便说一句,使用此解决方案,不需要释放变量(例如虚拟析构函数),对吗?对于
std::unique_ptr
,基类应该有虚拟析构函数(但不必手动调用delete)。使用
shared\u ptr
,它将不是必需的。@RSahu:
process()
似乎不是模型创建的一部分,这就是我省略它的原因。我添加的用例更类似于OP的代码。谢谢你的快速回答!我一提交问题就看到了,但我花了一些时间来测试。它起作用了!但似乎std::make_unique只是C++14,不是吗?我必须使用C++14进行编译。有没有办法让它在C++11中工作?您仍然可以实现自己的
make_unique
或将
unique_ptr
构造函数与new一起使用。谢谢。顺便说一句,使用此解决方案,不需要释放变量(例如虚拟析构函数),对吗?对于
std::unique_ptr
,基类应该有虚拟析构函数(但不必手动调用delete)。使用
shared\u ptr
,不需要它。谢谢,但“切换”对我来说足够简单+1.无论如何,谢谢,但是“开关”对我来说很简单+1无论如何。
auto model = importModel(model_type, gm);
if ( model )
{
   model->process();
}