我得到了三个课程MachineLearning
,MachineLearningSVM
和MachineLearningAdaboost
。
MachineLearning
是基类,MachineLearningSVM
和MachineLearningAdaboost
来自它。
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类型。
我怎样才能实现这种情况?我想避免使用模板。
答案 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响应中所述。