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

时间:2017-05-12 16:40:06

标签: c++ class oop inheritance

已发布并回答了类似问题herehere,但建议的解决方案对我不起作用。

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

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; 
};

子模型是父模型的特例,可以存储在更简单的结构中,因此可以更快地处理。

我想要做的是实例化模型,具体取决于用户指定的输入参数model_type,如下所示:

Model* model;
switch(model_type){
case 1:
    model = new SpecialModel;
    model->importSpecialModel(gm);
    break;
case 2:
    model = new SpecialSpecialModel;
    model->importSpecialSpecialModel(gm);
    break;
default:
    model = new Model;
    model->importModel(gm);
    break;
}

model->process();

使用上面的代码,我收到了以下错误:

  

'class Model'没有名为'importSpecialModel'的成员

     

'class Model'没有名为'importSpecialSpecialModel'的成员

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

2 个答案:

答案 0 :(得分:5)

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

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;
        }
    }
}

然后

auto model = CreateModel(model_type, gm);
model->process();

答案 1 :(得分:1)

这是the answer by @Jarod42的变体。您可以通过使用函数指针映射来避免使用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 {};
   }
}

并将其用作:

auto model = importModel(model_type, gm);
if ( model )
{
   model->process();
}