GSL中的静态虚拟变通方法

时间:2012-05-21 14:40:51

标签: c++ static virtual

您好我正在尝试使用GNU Scientific Library中的微分方程包编写一个小程序来模拟动态系统。问题不是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
};

1 个答案:

答案 0 :(得分:6)

我假设函数定义中的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[]);
};