将指向成员函数的指针转换为普通指针

时间:2010-11-18 01:02:12

标签: c++ pointers casting

目前我有一类此类,为简单起见缩短了:

class MyClass {
    public: 
        MyClass();
        void* someFunc(void* param);
}

现在我需要调用这种类型的函数(不是任何类的成员,不幸的是无法更改),但无论如何我需要调用它:

void secondFunc(int a, int b, void *(*pCallback)(void*));

现在我需要传递一个实例的someFunc的地址。

不工作的样本:

MyClass demoInstance;
// some other calls
secondFunc( 1, 2, demoInstance::someFunc() );

我也尝试使用像:

这样的演员
(void* (*)(void*)) demoInstance::someFunc;
reinterpret_cast<(void* (*)(void*))>(demoInstance::someFunc);

如何使用类'成员函数作为参数调用此函数,以便此函数可以将其用作回调?

任何想法或评论都表示赞赏。感谢致敬 托拜厄斯

7 个答案:

答案 0 :(得分:8)

您无法直接调用成员函数。 成员函数指针与函数指针的类型不同。

你需要以某种方式将它包装在兼容的功能中。但是,如果您的外部函数(将函数指针作为参数的函数)不可重入并且不提供额外的参数供函数指针使用,则您将无法传递成员所使用的实例功能运作,所以你实际上无法拨打电话。

答案 1 :(得分:5)

C函数和C ++成员函数之间的区别在于C函数使用 cdecl 调用约定,而成员函数使用 thiscall 调用约定(并且你不能甚至拿他们的地址!)。

据我了解,您实际上希望secondFunc()调用特定类的实例的成员函数(让我们称之为this)。那么,特定类的所有实例的成员函数的地址是相同的。为了将指针传递给对象,您需要一个侧面通道。在这种情况下,它可以是静态变量。或者,如果您需要MT支持,则必须使用线程本地存储(TLS),

这需要每个SomeFunc类型成员进行一次回调,但无论如何你都需要一个调度员。

答案 2 :(得分:1)

答案 3 :(得分:0)

class MyClass 
{
public: 
    MyClass();
    void* someFunc(void* param);
};

void* callback(void*)
{
    MyClass instance;
    instance.someFunc(0 /* or whatever */);
}

void foo()
{
    secondFunc( 1, 2, callback);
}

答案 4 :(得分:0)

之前没有看到关于无法改变第二个功能的部分。

使用指向成员函数和对象的指针定义结构:

struct MyData {
   MyStruct  *myInstance;
   (void *)(MyStruct::myFunction)(void *data);
   void * dataPointer ;
}

创建一个可以调用正确方法的函数:

void *proxyFunc( MyData *data)
{
  return (data->myInstance->*(data->myFunction))(data->dataPointer);
}

然后将函数2调用为:

MyData  dataP = { someInstance, &MyStruct::someFunc, &dataPtr };
secondFunc(proxyFunc, &dataP);

答案 5 :(得分:0)

请参阅此示例:

#include <iostream>

class MyClass 
{
public: 
    MyClass()
    {
    }

    void* someFunc(void* param)
    {
        std::cout << "someFunc" << std::endl;
        return (void*)0;
    }
};

typedef void* (MyClass::*MemFun)(void*);

void secondFunc(int a, int b, MemFun fn)
{
    MyClass* ptr = 0;
    // This is dangerous! If the function someFunc do not operate the data in the class.
    // You can do this.
    (ptr->*fn)(0);
    std::cout << "Call me successfully!" << std::endl;
}

int main()
{
    secondFunc(1, 2, &MyClass::someFunc);

    system("pause");

    return 0;
}

答案 6 :(得分:0)

使用 union 很容易

#include <iostream>

using namespace std;

class Data {
public:
    Data(const int data) : num(data) {

    }

    void printData() const {
        printf("%d", this->num);
    }

private:
    int num;
};

union Test {
    decltype(&Data::printData) member_fun;

    void (* normal_function)(...);
};

int main() {
    Test t;
    t.member_fun = &Data::printData;
    Data data(10);
    (*t.normal_function)(&data);
}