我想实现一个密度为R ^ n的概率空间,如下所示:
typedef struct _ProbabilitySpace {
int dim;
double (*density)(double *first, double *last);
/** more stuff **/
} ProbabilitySpace;
现在,通过这种实现,如何实现一系列密度函数?可以说,我想实现高斯族,然后我可以写一个函数
double gaussian(struct vec mu, struct mat sigma, double *first, double *last){
/** gaussian density function here */
}
如您所见,此密度不仅取决于参数* first和* last,还取决于mu和sigma。我想给用户一个指定mu和sigma的可能性(可能在运行时),而不必一直传递它。此外,此函数可能用于不同ProbabilitySpace对象中的(mu,sigma)的不同组合。
C ++中的解决方案是创建另一个类:
class _Density{
public:
double evaluate(double* first, double* last);
private:
/** any private parameters **/
};
任何一组概率分布都可以从该类继承并定义私有参数,用户必须在构造函数中初始化这些参数。然后,评估成员函数可以访问这些私有参数。
但是在C中,我没有看到任何方法来为任何函数指定参数列表以外的参数,因为它们无法访问其他成员变量。
也许有人可以建议解决方案?
答案 0 :(得分:2)
任何一组概率分布都可以从该类继承并定义私有参数,用户必须在构造函数中初始化这些参数。然后,评估成员函数可以访问这些私有参数
你知道,C ++每次都会将隐藏参数this
传递给成员函数evaluate
,这允许使用这些私有参数。在C中你必须自己做。
struct _Density{
/** any private parameters **/
} d;
InitDensity(&d, ...); /* constructor */
gaussian(&d, first, last);
/* etc. */
实际上,C ++编译器会自动为您完成同样的工作。
答案 1 :(得分:0)
您的C ++解决方案也不起作用,因为指向成员函数_Density::evaluate
的指针与double (*density)(double *first, double *last)
函数指针类型不兼容。
这种不兼容的原因是非静态成员函数隐式地使用了额外的参数this
。编译器隐藏了该参数的存在,但它存在。
C ++中的解决方案是使用std::function
代替函数指针。但是,在C中不能做同样的事情,所以惯用解决方案是将类型void*
的额外参数传递给系列中的所有函数,让它们在内部“破解”参数,提取无论他们需要什么:
typedef struct _ProbabilitySpace {
int dim;
double (*density)(double *first, double *last, void *user_data);
/** more stuff **/
} ProbabilitySpace;
typedef struc {
struct vec mu;
struct mat sigma;
} GaussianData;
double gaussian(double *first, double *last, void *user_data){
GaussianData *data = (GaussianData*)user_data;
...
}
这种方法统一了函数签名,允许将各种参数传递给指针调用的函数。您需要确保这些参数在函数指针可以访问它们时保持有效,例如,您没有存储指向即将超出范围的本地的指针。
答案 2 :(得分:0)
您可以通过以下方式执行此操作
typedef struct _ProbabilitySpace {
int dim;
double (*density)(double *first, double *last);
/** more stuff **/
} ProbabilitySpace;
//...
double gaussian( double *first, double *last )
{
//...
gaussian_impl( /*...*/ );
}
static double gaussian_impl(struct vec mu, struct mat sigma, double *first, double *last){
/** gaussian density function here */
}
//...
ProbabilitySpace p;
p.density = gaussian;