C++ 类成员函数的GSL集成

C++ 类成员函数的GSL集成,c++,class,integration,gsl,C++,Class,Integration,Gsl,我有一门课叫宇宙。该类包含用于计算距离的成员函数,并需要对丑陋的函数进行数值积分。我试图使用GSL执行集成,但在尝试编译库时出现以下错误- $ g++ -c -O3 -std=c++11 Universe.cpp -o Universe.o $ error: cannot convert ‘Universe::Hz’ from type ‘double (Universe::)(double, void*)’ to type ‘double (*)(double, void*)’ 下面是没有构

我有一门课叫宇宙。该类包含用于计算距离的成员函数,并需要对丑陋的函数进行数值积分。我试图使用GSL执行集成,但在尝试编译库时出现以下错误-

$ g++ -c -O3 -std=c++11 Universe.cpp -o Universe.o
$ error: cannot convert ‘Universe::Hz’ from type ‘double (Universe::)(double, void*)’ to type ‘double (*)(double, void*)’
下面是没有构造函数的类宇宙(为了简洁):

宇宙
\ifndef UNIVERSE\u H
#定义宇宙
#包括
#包括
使用名称空间std;
阶级宇宙{
私人:
静态常数双c=299792458.0,Mpc2Km=3.08567758e+19,Yrs2Sec=3.15569e7;
双H0=67.77,OmegaM=(0.022161+0.11889)/(H0*H0),OmegaL=0.6914,OmegaG=8.24e-5,OmegaK=0.0009;
双Ez(双z);
双Hz(双z,无效*参数);
公众:
双区,时间;
Universe()=默认值;
宇宙(双h0);
宇宙(双欧米伽,双欧米伽);
宇宙(双h0,双欧米伽,双欧米伽);
宇宙(双欧米伽,双欧米伽,双欧米伽,双欧米伽);
宇宙(双h0,双欧米伽,双欧米伽,双欧米伽,双欧米伽);
//双半径();
//双倍年龄();
双区(双z);
};
#恩迪夫
Universe.cpp
#包括
#包括
#包括“Universe.h”
使用名称空间std;
双宇宙::Hz(双z,空*参数){
双倍结果=1.0/pow(ω+pow(1.0+z,3.0)*ω+pow(1.0+z,4.0)*ω+pow(1.0+z,2.0)*ω+pow(0.5);
返回结果;
}
双宇宙::distC(双z){
双下限=0.0,绝对误差=1.0e-8,相对误差=1.0e-8,α=0.0,结果,误差;
gsl_集成_工作空间*work_ptr=gsl_集成_工作空间_alloc(1000);
gsl_函数Hz_函数;
void*params_ptr=α
Hz_function.function=Universe::Hz;
Hz_function.params=参数_ptr;
gsl_积分_qags(&Hz_函数、下限、z、abs_误差、rel_误差、1000、工时、结果和误差);
返回distH*结果;
}
我不太知道如何解决此问题,根据以下文档,我第一次使用GSL: 以及以下指南:
感谢您的关注和解答

更改HZ的方法名称时会发生什么情况?

尝试以下操作:使您的
HZ
函数保持静态,如下所示:

static double Hz(double z, void* params) 
我验证了这与您的代码一起工作

我不是专家,但我相信(下面是波浪式的解释)基本问题是,由于
gsl_函数
结构需要一个指向函数的指针(即
double*
),编译器不喜欢使用来自“对象”的类方法,而“对象”甚至还没有实例化。然而,使函数在类中保持静态意味着编译器甚至在类的实例存在之前就知道在哪里可以找到函数,并且可以使用指向该函数的指针进行处理。(也许有人能给出比这更好的解释,但希望我在这方面没有偏离太远。)


希望这能有所帮助。

在[1][1]有一个众所周知的解决方案:
#include <cmath>
#include <gsl/gsl_integration.h>
#include "Universe.h"

using namespace std;

double Universe::Hz(double z, void* params)  {
    double result = 1.0/pow(OmegaL + pow(1.0+z,3.0)*OmegaM + pow(1.0+z,4.0)*OmegaG + pow(1.0+z,2.0)*OmegaK, 0.5);
    return result;
    }

double Universe::distC(double z) { 
    double lower_limit = 0.0, abs_error = 1.0e-8, rel_error = 1.0e-8, alpha = 0.0, result, error;
    gsl_integration_workspace *work_ptr = gsl_integration_workspace_alloc(1000);
    gsl_function Hz_function;
    void* params_ptr = &alpha;
    Hz_function.function = Universe::Hz;
    Hz_function.params = params_ptr;
    gsl_integration_qags(&Hz_function, lower_limit, z, abs_error, rel_error, 1000, work_ptr, &result, &error);
    return distH*result;
    }
static double Hz(double z, void* params)