我现在正在为此寻找一个解决方案。没有发现任何相关问题足以令人遗憾地回答所以这是我的问题。 考虑下一个代码:
// dummy class A
class A {
public:
void aFunction() { // <- this is the function I want to point at
cout << "aFunction() is called\n";
}
};
class B {
public:
template <class Class> // get a function pointer
void setFunction( void (Class::*func)() ) {
p_func = func;
}
void (*p_func)(); // the function pointer
}
int main() {
B obj;
objb.setFunction(&A::aFunction);
return 0;
}
setFunction()
p_func = func;
上的编译错误:
无法从'void(__ thiscall A :: *)(void)'转换为'void(__ cdecl *)(void)'
我似乎无法以任何方式摆脱它。我知道它与那些不可见的this
指针(__thiscall
和__cdecl
)有关,但我不知道如何处理它们。我尝试使成员变量p_func
也成为一个类模板(void (Class::*p_func)()
),因此它具有相同的结构,但是在一个类中有两个类模板似乎是非法的(为什么?),因此不是正确的解决方案。这次编译器抱怨:
不允许使用多个模板参数列表
这个方法(没有模板)完全适用于全局函数(这是我目前使用的解决方法),我看到它在库(sfgui)中的使用,所以它应该是完全可能的。
要了解我为什么要这样做的背景:我正在尝试创建一个按钮。这个按钮应该可以调用我想要的任何功能。现在,我希望它能调用我正在制作的动画类的start()
函数。
p.s:我知道这个例子没用,因为我无法运行p_func
:该函数不是静态的。我仍然需要添加一个对象指针(setFunction( void (Class::*func)(), Class* )
),但这似乎不是问题。我知道typedef
使函数指针更具可读性,但不能使用类模板。
经过一些研究后,我认为答案我不需要回答这个问题,而是另一个问题。这一次,我注意到事实上允许多个template <class Class>
。但是,它不允许在成员变量上,因为编译器不可能知道他需要使用哪个class
这可能是错误的原因
不允许使用多个模板参数列表
这是一个奇怪的描述。无论如何,谢谢你的帮助,你确实给了我更好的见解。
答案 0 :(得分:3)
您无法将指向成员Class::*func
的指针转换为普通函数指针。它们有不同的类型。
你应该转过来:
void (*p_func)(); // the function pointer
进入这个:
void (class::*p_func)(); // the function pointer
您还可以使用std::function<void()>
并使用boost::bind
绑定它。
std::function<void()> fun = boost::bind(class::member_fun, args);
修改强>
如何将B类设为模板,以便执行此操作:
#include<iostream>
class A {
public:
void aFunction() { // <- this is the function I want to point at
std::cout << "aFunction() is called\n";
}
};
template<class T>
class B {
public:
void setFunction( void (T::*func)() ) {
p_func = func;
}
void (T::*p_func)(); // the function pointer
void callfunc()
{
(t.*p_func)(); //call pointer to member
}
private:
T t;
};
int main() {
B<A> obj;
obj.setFunction(&A::aFunction);
return 0;
}
答案 1 :(得分:0)
我在寻找一种方法来保存未知类型的对象而不使用已经回答here的模板或无效指针时,我找到了完整的答案。解决方案有点狡猾,因为您必须创建一个允许某些转换的虚拟父级。
我们的想法是创建一个Parent,并且允许指向的每个对象都必须从中继承。这样你可以创建一个指针Parent *obj
,它可以容纳多种类型的对象,但当然只有从Parent
继承的类。
这同样适用于函数指针。如果将指针定义为void (Parent::*func)()
作为成员变量。您可以向用户询问模板函数指针template <class Class> setFunction( void (Class::*f)() )
,它可以保存任何类的指针。现在,您需要将函数指针强制转换为所需的类Parent
:static_cast<void(Parent::*)()>(f)
。请注意,这仅在Class继承自Parent时才有效。否则你会收到编译错误。
#include <iostream>
using namespace std;
// dummy class Parent
class Parent {};
// class A
class A : public Parent { // Mind the inheritance!
public:
A(int n) : num(n) {}
void print() { // <- function we want to point to
cout << "Number: " << num << endl;
}
int num;
}
// class B, will hold the 2 pointers
class B {
public:
B() {}
template <class Class> // will save the function and object pointer
void setFunction( void (Class::*func)(), Class *obj) {
function = static_cast<void(Parent::*)()>(func);
object = obj;
}
void execFunction() { // executes the function on the object
(object->*function)();
}
void (Parent::*function)(); // the function pointer
Parent *object; // the object pointer
}
int main() {
A a(5);
B b;
b.setFunction(&A::print, &a);
b.execFunction();
return 0;
}
我真的不喜欢这个解决方案。一个更好的解决方案是类B
可以有一个函数,当需要执行函数时它返回一个bool。这样,您只需在执行所需函数的if
函数中放置main
语句。
A a(5);
B b;
while (;;) {
if (b.aTest())
a.print();
}
B::aTest()
声明为
bool B::aTest();
希望这有助于遇到同样问题的任何人。所以这是完全可能的,但在我看来非常狡猾,我不鼓励人们使用第一种方法。