我在编写一个实现"数学函数"的类。
这个"数学质量函数"可以从一个抽象类
现在的问题是,当我想要通过组合派生对象来创建线性组合的MathFunctions时,我需要创建一个新对象,该对象仍然是一个MathFunction实例,并具有它们的成员变量和方法,但存储的质量是其组件质量的线性组合。例如,我想在MathFunction上实现operator+重载,以允许我创建类似以下内容的东西:
但是我不能这样做,因为MathFunction的构造函数是虚拟的!所以问题是,如何组合派生自MathFunction的不同对象,生成一个可以作为MathFunction传递给我的Maximizer类的对象? 完整代码可在coliru上找到http://coliru.stacked-crooked.com/a/3c33664066a3658b。
这个"数学质量函数"可以从一个抽象类
QualityFunction
派生出来。它包含一个mutable double quality
,一旦计算出函数值就会被存储为标量值,还包括一个eval
方法。这个方法需要每个派生类自己实现,因为它是一个纯虚方法。#include <vector>
#include <iostream>
#include <cmath>
using std::cout;
using std::cerr;
using std::endl;
using std::sin;
using std::cos;
using std::vector;
class MathFunction
{
protected:
mutable double quality; // mutable keyword allows to modify quality even in const methods.
virtual void eval(const vector<double> &x) const = 0;
public:
virtual ~MathFunction() {}
double &operator()()
{
return quality;
}
double &operator()(const vector<double> &x) const
{
eval(x);
return quality;
}
};
那么从QualityFunction
派生的每个子类都必须实现eval
方法,因为有许多可能的QualityFunction
。两个例子是SumSinFunction和SumCosFunction,它们计算其参数的sin
和cos
之和:
class SumSinFunction : public MathFunction
{
public:
SumSinFunction(){};
~SumSinFunction() {};
protected:
void eval(const vector<double> &x) const
{
quality = 0;
for (size_t i=0; i<x.size(); ++i)
quality += sin(x[i]);
}
};
class SumCosFunction : public MathFunction
{
public:
SumCosFunction(){};
~SumCosFunction() {};
protected:
void eval(const vector<double> &x) const
{
quality = 0;
for (size_t i=0; i<x.size(); ++i)
quality += cos(x[i]);
}
};
这种层次结构的设计是为了使类Maximizer
能够接受MathFunction
对象,并通过重复调用eval
方法来寻找一个解决方案,即使得一个vector<double> x
最大化整体质量。
class Maximizer
{
public:
Maximizer(){}
vector<double> maximize(const MathFunction &f)
{
// do some operations to maximize it
// and return the maximized value
return std::vector<double>();
}
};
现在的问题是,当我想要通过组合派生对象来创建线性组合的MathFunctions时,我需要创建一个新对象,该对象仍然是一个MathFunction实例,并具有它们的成员变量和方法,但存储的质量是其组件质量的线性组合。例如,我想在MathFunction上实现operator+重载,以允许我创建类似以下内容的东西:
SumCosFunction cosfun;
SumSinFunction sinfun;
MathFunction m = cosfun + sinfun;
首先尝试使用友元函数重载operator+
friend MathFunction& operator+(const MathFunction &f1, const MathFunction &f2)
{
MathFunction *f;
// do something
}
但是我不能这样做,因为MathFunction的构造函数是虚拟的!所以问题是,如何组合派生自MathFunction的不同对象,生成一个可以作为MathFunction传递给我的Maximizer类的对象? 完整代码可在coliru上找到http://coliru.stacked-crooked.com/a/3c33664066a3658b。
int main()
{
vector<double> x;
for (int i=0; i<10;i++)
x.push_back(i);
SumCosFunction cosfun;
SumSinFunction sinfun;
//MathFunction F;// = cosfun+sinfun;
Maximizer opt;
opt.maximize(cosfun);
return 0;
}
MathFunction
派生一个类(例如ContainerFunction
)吗? 这个ContainerFunction
可以存储一个MathFunction
对象列表(例如std::vector
),当调用eval
时,这些对象都会被执行。 - Simon KraemerMathFunction.pimpl -> MathFunctionImpl
,并且你的数学类继承自MathFunctionImpl
。这样就不会有运算符重载的问题了。 - eferion