C ++类成员函数回调

时间:2011-11-10 12:21:55

标签: c++ class function callback member

我有以下问题。我有一个来自外部库(无法修改)的函数,如下所示:

void externalFunction(int n, void udf(double*) );

我想将udf函数作为现有类的函数成员传递。请查看以下代码:

// External function (tipically from an external library)
void externalFunction(int n, void udf(double*) )
{
     // do something
}

// User Defined Function (UDF)
void myUDF(double* a)
{
      // do something
}

// Class containing the User Defined Function (UDF)
class myClass
{
public:
    void classUDF(double* a)
    {
        // do something...
    };
};

int main()
{
    int     n=1;

    // The UDF to be supplied is myUDF
    externalFunction(n, myUDF);

    // The UDF is the classUDF member function of a myClass object
    myClass myClassObj;
    externalFunction(n, myClassObj.classUDF);   // ERROR!!
}

我不能将classUDF成员函数声明为静态函数,因此上面代码的最后一行会导致编译错误!

3 个答案:

答案 0 :(得分:6)

这是不可能的 - 在c ++中,你必须使用自由函数或静态成员函数,或者(在c ++ 11中)没有捕获的lambda来获取函数指针。

GCC允许你创建嵌套函数,它可以做你想要的,但只能在C中。它使用所谓的trampolines来做到这一点(基本上是一小块动态生成的代码)。可以使用此功能,但前提是您将一些调用externalFunction的代码拆分为单独的C模块。

另一种可能性是在运行时生成代码,例如。使用libjit

因此,如果你对非重入函数没问题,请创建一个全局/静态变量,该变量将指向this并在静态函数中使用它。

class myClass
{
public:
    static myClass* callback_this;
    static void classUDF(double* a)
    {
        callback_this.realUDF(a);
    };
};

它真的很可怕的代码,但我担心你的externalFunction这样糟糕的设计会让你失望。

答案 1 :(得分:5)

您可以使用Boost绑定或TR1绑定(在最近的编译器上);;

<击>

<击>
externalFunction(n, boost::bind(&myClass::classUDF, boost::ref(myClassObj)));

<击>

不幸的是,在过去的10分钟里我一直梦想着。前进的唯一方法是使用某种静态包装函数调用目标。其他答案有各种简洁(特定于编译器)的花絮,但这里是主要技巧:

void externalFunction(int n, void (*udf)(double*) )
{ double x; udf(&x); }

myClass myClassObj;
void wrapper(double* d) { myClassObj.classUDF(d); }

int main()
{
    externalFunction(1, &wrapper);
}

的std ::功能&LT;&GT;

将绑定函数存储在如下变量中:

std::function<void(double*)> stored = std::bind(&myClass::classUDF, boost::ref(myClassObj))

(假设编译器现在支持C ++ 0x。我确定Boost在某处有一个boost :: function&lt;&gt;)

Vanilla C ++指针到成员函数

没有这样的魔法,你需要指向成员函数的指针语法:

另见http://ideone.com/Ld7It

  

编辑以向评论者澄清,显然这仅适用于 iff 您可以控制externalFunction的定义。这是对OP中的/ broken / snippet int的直接响应。

struct myClass
{
    void classUDF(double* a) { };
};

void externalFunction(int n, void (myClass::*udf)(double*) )
{
    myClass myClassObj;
    double x;
    (myClassObj.*udf)(&x); 
}

int main()
{
    externalFunction(1, &myClass::classUDF);
}

C ++ 98惯用解决方案

// mem_fun_ref example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>

int main () 
{
    std::vector<std::string> numbers;

    // populate vector:
    numbers.push_back("one");
    numbers.push_back("two");
    numbers.push_back("three");
    numbers.push_back("four");
    numbers.push_back("five");

    std::vector <int> lengths (numbers.size());

    std::transform (numbers.begin(), numbers.end(), lengths.begin(), 
                std::mem_fun_ref(&std::string::length));

    for (int i=0; i<5; i++) {
        std::cout << numbers[i] << " has " << lengths[i] << " letters.\n";
    }
    return 0;
}

答案 2 :(得分:2)

当我的MyClass是单身时,我就是这样做的:

void externalFunction(int n, void udf(double) );

class MyClass
{
public:
   static MyClass* m_this;
   MyClass(){ m_this = this; }
   static void mycallback(double* x){ m_this->myrealcallback(x); }
   void myrealcallback(double* x);
}

int main()
{
   MyClass myClass;
   externalFunction(0, MyClass::mycallback);
}