MathFunction
共通の実装がない場合、それは何のためですか?
その目的が 2 つの実装に共通のインターフェイスを提供することである場合は、それをどこで使用するかを検討してください。
- テンプレート化されていない (または非依存の) コードで、実行時に実装タイプが合理的に変化する可能性がある場合
- の型に合理的に依存する可能性のあるテンプレート化さ
MathFunction
れたコード、または使用している型を常に静的に認識しているコード
ケース 1 では、戦略パターンのようなものを使用するのが合理的です。MathFunction
仮想戦略にディスパッチする静的に型指定されたラッパーにするか、抽象 MathFunction 基本クラスを記述して、2 つの具象サブクラスのいずれかをインスタンス化することができます。
dasblinkenlightはすでに Strategy バージョンのデモを行っているので、これに相当する ABC を次に示します (ファクトリ関数を使用して実装の詳細を非表示にする方法に注意してください)。
// public header
class MathFunction {
public:
virtual ~MathFunction() {}
virtual double operator() (double radius, double angle) = 0;
};
MathFunction* make_function(Functor& function);
MathFunction* make_function(Mat<double> interpolationValues);
// implementation
class FunctorMathFunction : public MathFunction {
Functor& _function;
public:
FunctorMathFunction(Functor& function) : _function(function) {}
virtual double operator() (double radius, double angle) {
return _function(radius, angle);
}
};
class TableMathFunction : public MathFunction {
Mat<double> _interpolationValues;
public:
TableMathFunction (Mat<double> interpolationValues)
: _interpolationValues(interpolationValues) {}
virtual double operator() (double radius, double angle) {
return ...; // Use _interpolationValues to do calculation
}
};
MathFunction* make_function(Functor& function) {
return new FunctorMathFunction(function);
}
MathFunction* (Mat<double> interpolationValues) {
return new TableMathFunction(interpolationValues);
}
ケース 2 では、テンプレート化MathFunction
が適切な選択です。それを (部分的に) 特殊化するか、評価をデリゲートする Policy クラスで MathFunction をパラメーター化することである Strategy パターンに相当するコンパイル時を使用することができます。パフォーマンスが問題になる場合は、仮想関数呼び出しを保存する (およびインライン化を有効にする) と役立つ場合があります。
template <typename EvaluationPolicy>
class MathFunction
{
EvaluationPolicy eval;
public:
MathFunction() {}
MathFunction(EvaluationPolicy const &ep) : eval(ep) {}
double operator() (double radius, double angle) {
return eval.calc(radius, angle);
}
};
class FunctionPolicy
{
std::function<double(double,double)> func;
public:
FunctionPolicy(std::function<double(double,double)> f) : func(f) {}
double calc(double r, double a) { return func(r, a); }
};
class TablePolicy
{
Mat<double> mat;
public:
TablePolicy(Mat<double> values) : mat(values) {}
double calc(double r, double a) { return ....; }
};
FunctionMathFunction
2 つの別個の具象クラス (および)を記述するだけでなくポリシーを使用する利点は、それらの関係を示すこと、ポリシーに依存しないTableMathFunction
コードを共有すること、および関連のない問題を個別のポリシーに分割することができることです。