【发布时间】:2014-04-11 08:38:34
【问题描述】:
假设我有一个名为BinaryClassifier 的策略接口,它可以接受Sample 并返回一个double,表示Sample 对象属于正类的概率:
struct BinaryClassifier {
virtual ~BinaryClassifier(){}
virtual double classify(std::shared_ptr<Sample> sample) const = 0;
};
我们可能有多个BinaryClassifier 的实现,例如LogisticRegressionBinaryClassifier。
Sample 又是一个只公开两个方法的接口:
struct Sample {
virtual ~Sample() {}
InputFeatures const& get_input_features() const = 0;
double get_label() const = 0;
};
除了这两种方法,Sample 的具体实现暴露了完全不同的接口(即它们是不相关的),它们唯一的共同点是它们可以被二进制分类器分类。
到目前为止一切顺利。
当我们决定引入BinaryClassifier::train 方法时,问题就出现了:
struct BinaryClassifier {
virtual ~BinaryClassifier(){}
virtual double classify(std::shared_ptr<Sample> sample) const = 0;
virtual void train(std::vector<std::shared_ptr<Sample>> samples) = 0;
};
此时,以下内容将不起作用:
std::vector<std::shared_ptr<ConcreteSample>> concreteSamples = ...;
concreteBinaryClassifier.train(concreteSamples);
那是因为std::vector<std::shared_ptr<ConcreteSample>> 和std::vector<std::shared_ptr<Sample>> 是两个不相关的类型。
C++-ish 解决方案是依赖模板:
template<class SampleType>
virtual void train(std::vector<std::shared_ptr<SampleType>> samples) = 0; // non-working code, template method cannot be virtual
但是模板方法不能是virtual。尽管如此,我希望BinaryClassifier 成为一个策略接口,因为可能存在尽可能多的BinaryClassifier 实现。在这一点上,即使设计看起来很合理,我也陷入了死胡同。
编辑:此外,给定的BinaryClassifier 对象可能会使用ConcreteSampleA 的向量进行训练,同时对ConcreteSampleB 类型的对象进行分类
哪种是最适合 C++ 的建模方式?
【问题讨论】:
标签: c++ templates polymorphism containers covariance