类成员函数指针的调用
临近毕业,手上剩余工作不太多了,想趁机把以前的部分代码重新整理一下,同时把以前用的数学运算库(Numerical Receipe in C)换成GSL(Gnu Scientific Library)。
首先我打算用C写一个通用的Monte Carlo采样的库,比如Metropolis-Hastings sampling:
/* args: c_state - continuous states
d_state - discrete states
logpos - function to evaluate log posterior of states
vp - extra information */
int mc_metrohast ( double* c_state, int* d_state, double (*logpos) (double*, int*, void*), void *vp );
这样就可以调用这个函数进行采样,只需要提供当前Markov chain的状态(c_state, d_state)和评价log后验概率的函数指针logpos,如果需要的话其他信息可以用过指针vp来传递。
现在问题来了。我的模型都封装在一个类里面,比如说Gaussian process:
class CGp:{
...
public:
void sample();
double logpos();
...
};
成员函数sample()如下:
void sample()
{
...
int acc = mc_metrohast ( c_state, d_state, logpos, NULL );
...
}
这样是不行的,因为logpos是CGp的类成员函数,其函数指针不能这样简单传递给mc_metrohast,除非mc_metrohast定义如下:
int mc_metrohast ( double* c_state, int* d_state, double (CGp::*logpos) (double*, int*, void*), void *vp );
但是这样的话要为每一个模型的类都重写一个mc_metrohast函数 ...
最后我逼不得已用了一个很土的解决办法,那就是写一个标准C函数logposext,用它调用CGp类成员函数来计算后验概率,这样logposext就可以作为普通函数指针传递给mc_metrohast了:
double logposext (double* c_state, int* d_state, void *vp)
{
CGp * gp = (CGp*) vp;
double logpos = gp->logpos();
return logpos;
}
此时vp指针用于传递类CGp的信息。