我最近一直在实施一种解决“转向点”问题的车辆控制算法。算法本身涉及多个矩阵ODE求解,我想以这样一种方式实现我的主算法类,即它独立于我们希望控制的系统(ODE)。
最直观的方法似乎是:
class EquationBase
{
public:
virtual ~EquationBase();
/* Due to supposed bug in odeint this class is not abstract and operator() is not pure virtual */
virtual void operator() (const state_type &x, state_type &dxdt, const time_type t);
/* method specific for the considered algorithm, this should be part of the interface */
virtual void setLambdas(std::vector<double> lambdas);
};
class VehicleEquation: public EquationBase
{
public:
VehicleEquation();
~VehicleEquation();
void operator() (const state_type &x, state_type &dxdt, const time_type t) override;
void setLambdas(std::vector<double> lambdas) override;
private:
/* here some fields/methods specific for the system */
};
class MyAlgorithm
{
public:
MyAlgorithm();
MyAlgorithm(EquationBase *eq);
void start();
private:
EquationBase *eqPtr_;
};
现在,每个系统都是EquationBase的子系统,可以通过 eqPtr 使用。不幸的是,odeint :: integrate_adaptive的第二个参数(ODE系统)必须是一个对象,而不是一个指针。为了绕过这个限制,我引入了一个包装器,它包含指向ODE系统的实际指针,但不需要自己使用虚函数:
class EquationWrapper
{
public:
void operator() (const state_type &x, state_type &dxdt, const time_type t)
{
(*eqPtr_)(x,dxdt,t);
}
void setEquation(EquationBase *eqPtr)
{
eqPtr_ = eqPtr;
}
private:
EquationBase *eqPtr_;
};
class MyAlgorithm
{
public:
MyAlgorithm();
/* somewhere here: eqWrapper_.setEquation(eq); */
MyAlgorithm(EquationBase *eq);
/* somewhere in the algorithm: odeint::integrate_adaptive( .... , eqWrapper_, ... ) */
void start();
private:
EquationWrapper eqWrapper_;
};
当然这个解决方案有效,但我想知道这是否安全,干净(显然odeint会多次复制我的方程指针,但除非我在包装器析构函数中明确声明它,否则不会删除它),并且在那里一种更好的方法来实现所需的行为(我想到模板,但发现这更糟)?
由于我没有在其他地方发现类似的问题,请参考我的解决方案,如果您需要以这种方式使用odeint。
答案 0 :(得分:1)
您还可以使用std::function
或boost::function
创建多态颂歌:
using equation = std::function< void( state_type const& , state_type& , time_type ) >;
class VehicleEquation {
// no virtual or override here
void operator() (const state_type &x, state_type &dxdt, const time_type t);
void setLambdas(std::vector<double> lambdas) ;
};
class MyAlgorithm
{
MyAlgorithm();
MyAlgorithm(equation eq) : m_eq( eq ) {}
void start()
{
// ...
integrate_adaptive( stepper , eq , x , t0 , t1 , dt , obs );
// ...
// You can not call setLambdas
}
private:
equation m_eq;
};