将指向虚拟成员函数的指针作为普通C函数的参数传递

passing a pointer to a virtual member function as argument to an ordinary C function

本文关键字:函数 参数传递 指针 虚拟成员      更新时间:2023-10-16

我需要你的帮助,因为我不知道如何实现以下目标(这可能根本不可能):

假设我有一个类似的类层次结构

class Base
{
public :
    .....
    virtual int fcn(unsigned, const double *, void *,unsigned, double)=0;
    ....
};
class Derived_1:public Base
{
public :
    .....
    int fcn(unsigned, const double *, void *,unsigned, double);
    ....
};
class Derived_2:public Base 
{
public :
    .....
    int fcn(unsigned, const double *, void *,unsigned, double);
    ....
};

我需要对成员函数fcn进行积分,我想使用数值积分包(S.G.Johnson,请参阅http://ab-initio.mit.edu/wiki/index.php/Cubature)它(除其他外)包含一个定义为:的例程

int h_cubature(unsigned fdim, integrand f, etc ..);

其中f表示指向要积分的函数的指针,"被积函数"是typedef:

typedef int (*integrand) (unsigned, const double *, void *,unsigned, double);

我想做的是向h_cubature传递一个指向成员函数fcn的指针,我想集成它(此外,通过多态机制,即给定基类类型的指针)。也就是说,类似的东西

int main()
    {
    Base* b;
    Derived_1 d1;
    b=&d1;
    hcubature(2, b->fcn, ........);  //<---I don't know how to pass b->fcn
    ....

如上所述,将b->fcn传递给h_cubature,导致GNU GCC编译器发出错误

cannot convert 'Base::fcn' from type 'int (Base::)(unsigned int, const double *, void*, unsigned int, double*)' to type 'integrand {aka int (*)(unsigned int,const double*, void*, unsigned int, double*)}'|

不管我做了什么,都失败了。我看到的问题是,即使被积函数和fcn都有相同的签名和返回类型,b->fcn是一个虚拟成员函数,而被积函数是一个C型普通函数。

有人能告诉我如何将b->fcn指针传递给h_cubature吗(或者可能告诉我这是不可能的)?

提前谢谢!

不能将C++(非静态)成员函数传递给C函数指针(直观地说,因为这些成员函数将this作为隐式形式参数)。

但是,integrand的第三个形式可能是一个任意的指针。因此,通过它传递对象的地址,并使用一些粘合extern "C"static函数作为integrand

static int my_integrand (unsigned i, const double *t, void *data, 
                         unsigned j, double x)
{
   Base* b = static_cast<Base*>data;
   assert (b != nullptr);
   return b->fcn(i,t,data,j,x);
}

我想您不需要将data传递给b->fcn(这样您就可以在BaseDerived1Derived2类中更正其签名…)

以后使用hcubature(fdim, my_integrand, &d1,。。。。。。

您正试图将指向类成员函数的指针作为参数传递,期望指针指向函数。这是不兼容的。

不能将其作为常规C函数传递,也不能使用lambda或bind。

如果您控制函数的void *参数,即它是您提供的"魔法cookie",您可以使用它来实际包含Base *指针,然后投射它并从中调用您的虚拟函数。

class Base
{
  public:
    virtual int fcn(unsigned, const double *,unsigned, double)=0; // no void * param
};
int BaseFcn( unsigned u1, const double * pd, void * pv unsigned u2, double d )
{
    Base * base = static_cast< Base * >( pv );
    return base->fnc( u1, pd, u2, d );
}

如果不是这样,并且您只想使用基类来确定要传递什么函数而不传递"this",则可以使用虚拟函数来返回函数。

class Base
{
 public:
    virtual integrand fcn() const = 0;
};