![](/img/trans.png)
[英]cast a pointer to member function in derived class to a pointer to abstract member function
[英]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.