C ++类继承派生类

时间:2015-11-13 14:34:18

标签: c++ inheritance

我得到了三个课程MachineLearningMachineLearningSVMMachineLearningAdaboost

MachineLearning是基类,MachineLearningSVMMachineLearningAdaboost来自它。

class MachineLearning;      //Base class
class MachineLearningSVM : public MachineLearning;   
class MachineLearningAdaboost : public MachineLearning;

class `MachineLearning` {
   public:
      virtual void Train();
}

class MachineLearningSVM : public MachineLearning {
   public:
       void Train(std::vector<Feature> features);
}

class MachineLearningAdaboost : public MachineLearning {
   public:
       void Train(std::vector<Feature> features, std::vector<Label> labels);
}

我的问题是我想告诉所有派生类他们应该保留一个函数Train(),但每个派生类应该能够在他们的方法定义中有不同的参数。如上所述,Adaboost需要(示例性地)额外的培训标签。

请考虑以下事项:

 int main(){
     MachineLearning* ml;
     switch(type){
         case SVM:
             ml = new MachineLearningSVM();
             break;
         case Adaboost:
             ml = new MachineLearningAdaboost();
             break;
     }
     ml->Train(std::vector<Feature>);
 }

C ++在编译时不知道要调用哪个Train函数,因为它不清楚它是SVM类型还是Adaboost类型。

我怎样才能实现这种情况?我想避免使用模板。

2 个答案:

答案 0 :(得分:0)

你从根本上误解了多态和继承的概念。派生类必须与基类具有 is-a 关系:MachineLearningSVM MachineLearning,特别是virtual在基类中声明的函数(但在派生类中定义或重写)将从指向base的指针调用。

在您的示例中,这没有任何意义:

MachineLearning*ptr = get_machine_learning(); // can be either derived class
ptr->Train();           // we don't know which derived class so what do you
                        // want to pass as arguments???

你可以定义一个更灵活的界面,但是你仍然有同样的问题(例外情况显而易见):

struct MachineLearning
{
  void Train(std::vector<Feature> const&features)
  {
    if(need_labels()) throw std::runtime_error("need labels to train");
    train(features);
  }
  void Train(std::vector<Feature> const&features,
             std::vector<Label> const&labels)
  {
    if(!need_labels()) std::cerr<<"WARNING: ignoring labels for training\n";
    train(features,labels);
  }
  virtual~MachineLearning() {}
protected:
  virtual void train(std::vector<Feature> const&) = 0;
  virtual void train(std::vector<Feature> const&,
                     std::vector<Label> const&) = 0;
  virtual bool need_labels() const = 0;
};

struct MachineLearningSVM : MachineLearning
{
protected:
  bool need_labels() const { return false; }
  void train(std::vector<Feature> const&features) override;
  void train(std::vector<Feature> const&features,
             std::vector<Label> const&) override
  { train(features); }
};

struct MachineLearningAdaboost : public MachineLearning
{
protected:
  bool need_labels() const { return true; }
  void train(std::vector<Feature> const&) override
  { throw std::runtime_error("need labels for training"); }
  void train(std::vector<Feature> const&features,
             std::vector<Label> const&labels) override;
};

这些错误和警告是代码设计不佳的标志......

答案 1 :(得分:0)

这里遇到的麻烦是,在C ++中,函数签名是使用其名称和传递给它的参数类型创建的。 基类包含带签名的函数

// green color for example
let color = UIColor(red: 0.0, green: 1.0, blue: 0.0, alpha 1.0)

label.backgroundColor = color

因此你的编译器开始大喊大叫。 您可以通过声明虚拟功能在技术上修复代码,但它不会真正起作用,因为您的设计中存在问题,如previos响应中所述。