GSL 中的静态虚拟解决方法

Static Virtual workaround in GSL

本文关键字:解决 方法 虚拟 静态 GSL      更新时间:2023-10-16

你好,我正在尝试编写一个小程序来模拟动态系统,使用GNU科学库中的微分方程包。问题不是特定于GSL,但我只是为您提供所有详细信息

在当前的设计中,我希望有一个抽象的Experiment类,其中所有复杂的函数都将由 gsl 库调用。显式系统的动力学将由两个函数定义,即 func 和 jacob,它们分别定义了特定的运动方程和雅可比函数。因此,我想在 Experiment 类中进行所有模拟,并且只用将由Experiment继承的特定类覆盖两个虚函数。

我遇到的问题是,作为虚拟方法,这些方法无法编译

error: argument of type ‘int (Experiment::)(double, const double*, double*, void*)’ does not match ‘int (*)(double, const double*, double*, void*)’

如果我使这两个函数静态,程序将编译,但我正在失去我想要为特定问题实现的功能。

显然,它们不能既是静态的又是虚拟的,那么有谁知道这个问题的任何解决方法吗?有什么建议可以更好地处理它吗?

提前谢谢。

编辑:下面的代码编译,但它们不是虚拟的

class Experiment
{
public:
    Experiment();
    ~Experiment();
    void setupExperiment();
    static int func(double t, const double y[], double f[], void *params);
    static int jac (double t, const double y[], double *dfdy, double dfdt[], void *params);
};
void Experiment::setupExperiment(){
    double mu = 10;
    gsl_odeiv2_system sys = {func, jac, 2, &mu}; //Here is the problem with virtual functions
}
class aSpecificProblem: public Experiment{
   // I want to implement just the func and jac function which should be virtual above
};

>我假设函数定义中的void*是用户指定的回调参数。在这种情况下,请使用此参数传递指向对象的指针,并使回调成为静态函数。在这个静态函数中,将此指针转换回正确的类型(Experiment*(,并调用函数的非静态版本。

class Experiment
{
public:
    Experiment();
    ~Experiment();
    void setupExperiment();
    static int static_func(double t, const double y[], double f[], void *params);
    static int static_jac (double t, const double y[], double *dfdy, double dfdt[], void *params);
    virtual int func(double t, const double y[], double f[]);
    virtual int jac (double t, const double y[], double *dfdy, double dfdt[]);
};
void Experiment::setupExperiment()
{
    gsl_odeiv2_system sys = {static_func, static_jac, 2, this}; //Here is the problem with virtual functions
}
int Experiment::static_func(double t, const double y[], double f[], void *params)
{
  return ((Experiment*)params)->func(t, y, f);
}
int Experiment::static_jac (double t, const double y[], double *dfdy, double dfdt[], void *params)
{
  return ((Experiment*)params)->jac(t, y, dfdy, dfdt);
}
class aSpecificProblem: public Experiment
{
public:
    virtual int func(double t, const double y[], double f[]);
    virtual int jac (double t, const double y[], double *dfdy, double dfdt[]);
};