繁体   English   中英

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

[英]Cast pointer to member function to normal pointer

目前我有一个这样的类,为简单起见缩短:

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);

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

任何想法或评论表示赞赏。 感谢并问候托比亚斯

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

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

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

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

这需要每个SomeFunc类型成员一个回调,但无论如何您都需要一个调度程序。

有一种方法可以做到这一点。 由于 C++ 名称被破坏,您不能将其直接用于非静态函数。但是,由于非静态函数与 C 函数具有相同的签名,因此您可以直接将它们用作回调。 因此,对于非静态函数,您可以使用静态函数包装器。 页面详细解释了这种方法。

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

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

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

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

定义一个带有指向成员函数和对象的指针的结构:

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);

请参阅此示例:

#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;
}

使用 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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM