将函数指针传递给函数
如果我想将任何类的非静态成员函数作为按钮的单击函数传递,应该怎么做?可能吗 ?如果是这样,我需要做什么?例如,在哪个类(EntityToolGUI在此处)按钮被初始化后,我想将其单击操作设置为该类的非静态成员函数(EntityToolGUI类的非静态成员函数)。将函数指针传递给函数
GUIButton.h
typedef void (*ptr2clickFunc)(void);
class GUIButton : public GUIObject {
private : void (*clickFunc)(void);
public : void setClickFunction(ptr2clickFunc clickFunc);
};
GUIButton.cpp
void GUIButton::setClickFunction(ptr2clickFunc clickFunc)
{
this->clickFunc = clickFunc;
}
EntityToolGUI.h
class EntityToolGUI {
public : EntityToolGUI();
protected : void addAnimation();
}
EntityToolGUI.cpp
void EntityToolGUI::addAnimation()
{
cout<<"add animation"<<endl;
}
EntityToolGUI::EntityToolGUI()
{
....
btnAddAnimation->setClickFunction(&EntityToolGUI::addAnimation);
}
我得到一个错误,没有匹配的函数调用GUIButton :: setClickFunction(无效(EntityToolGUI :: *)())
候选人是无效GUIButton :: setClickFunction(无效(*)() )
我该如何解决?
如果你想传递的obj乐趣PTR,你可以使用boost ::绑定和boost ::功能
使用boost的解决方案非常优雅,我想知道上述是否可能使用std库。 – 2012-07-13 05:38:45
然后使用mem_fun http:// cplusplus。com/reference/std/functional/mem_fun/ 或mem_fun_ptr http://cplusplus.com/reference/std/functional/mem_fun_ref/ 它可能有点难,但应该做的工作 – 2012-07-13 05:44:13
@JeffreyChen如果你的编译器是C + +11的能力,见例如['std :: bind'](http://en.cppreference.com/w/cpp/utility/functional/bind)和['std :: function'](http://en.cppreference.com/w/CPP /实用程序/功能/功能)。 – 2012-07-13 05:48:48
不能将指向非静态成员函数的指针作为指向“常规”非成员函数的指针。您应该使静态为addAnimation
,或者使ptr2clickFunc
typedef a pointer to member function。
请注意,调用指向成员函数的指针与调用函数指针不同,因为您必须提供将调用成员指针的实例。
如果我想要怎么办?传递任何类的非静态成员函数?可能吗 ?如果是这样,我需要做什么?例如,在哪个类中按钮被初始化,我想将其单击操作设置为该类的非静态成员函数。 – 2012-07-13 05:21:11
@JeffreyChen你不能创建一个能够保存任何类的成员函数的类型,但是如果这些类有一个共同的祖先,你可以存储该祖先的成员函数。当然,在这种情况下不需要,因为你可以使用虚函数而不是成员指针。 – dasblinkenlight 2012-07-13 10:32:04
addAnimation需要是静态函数。当回调函数按照您现在正在执行的方式进行设置时,类EntityTollGUI的对象不会随函数一起注册。
试试这个(C++ 11):
#include <stdio.h>
#include <stdlib.h>
#include <functional>
class Raiser
{
public:
std::function<void(int)> ev1, ev2;
void RaiseEv1()
{
if (!ev1._Empty())
ev1(44);
}
void RaiseEv2()
{
if (!ev2._Empty())
ev2(66);
}
};
class Handler
{
private:
int id;
std::function<void(int)> h;
public:
Handler(int newId)
{
id = newId;
h = [this](int i)
{
printf("Handler with id = %d captured event!\n", this->GetId());
};
}
void Hook1(Raiser & raiser)
{
raiser.ev1 = h;
}
void Hook2(Raiser & raiser)
{
raiser.ev2 = h;
}
int GetId()
{
return id;
}
};
int main(int argc, char * argv[])
{
Raiser raiser;
Handler handler1(1), handler2(2);
handler1.Hook1(raiser);
handler2.Hook2(raiser);
raiser.RaiseEv1();
raiser.RaiseEv2();
getchar();
}
AFAIK,这是使用C++的事件可以获得的最多,而不使用语言扩展。
传递函数指针的大部分(正派)C代码都使用额外的void *参数来传递用户上下文到函数。这在C++中并不常见(因为存在比函数指针更好的技术),但是如果由于某种原因而使用函数指针,那么它可能是合适的。
typedef void (*ptr2clickFunc)(void*);
class GUIButton : public GUIObject {
private : ptr2clickFunc clickFunc;
private : void * userdata;
public : void setClickFunction(ptr2clickFunc clickFunc, void* userdata);
};
class Foo
{
static void do_foo(void * userdata)
{
Foo* thisptr = static_cast<Foo*>(userdata);
thisptr->foo();
}
void foo() { ... }
};
int main()
{
Foo foo;
GUIButton button;
button.setClickFunction(&Foo::do_foo, &foo);
button.click();
}
编辑正如注意到鲍尔泰克,如果你做这个有很多,你可以提取静态函数成一个模板 - 它看起来有点像这样(含有少量errrors未经测试并可能)。
// GUIButton is as before
// Note no static function here
class Foo { void foo(); }
template<typename T, void(T::*FN)() >
void Call(void * data)
{
static_cast<T*>(data)->*FN();
}
int main()
{
Foo f;
GUIButton button;
button.setClickFunction(&Call<Foo,&Foo::foo>, &f);
button.click();
}
既然你已经在使用C++,那么如果每个类都不会有do_foo方法,并且使模板不在其中, – 2012-07-14 00:03:03
传递指向C++方法的指针时,你需要做额外的黑客攻击。请参阅http://mdzahidh.wordpress.com/2008/07/16/pointer-to-c-class-methods-or-should-you-call-em-method-pointers/ – 2012-07-13 05:10:19