你如何传递成员函数指针?
我正在试图将一个类中的成员函数传递给一个接受成员函数类指针的函数。 我遇到的问题是我不知道如何正确使用这个指针在类内做到这一点。 有没有人有build议?
这是传递成员函数的类的一个副本:
class testMenu : public MenuScreen{ public: bool draw; MenuButton<testMenu> x; testMenu():MenuScreen("testMenu"){ x.SetButton(100,100,TEXT("buttonNormal.png"),TEXT("buttonHover.png"),TEXT("buttonPressed.png"),100,40,&this->test2); draw = false; } void test2(){ draw = true; } };
函数x.SetButton(…)包含在另一个类中,其中“object”是一个模板。
void SetButton(int xPos, int yPos, LPCWSTR normalFilePath, LPCWSTR hoverFilePath, LPCWSTR pressedFilePath, int Width, int Height, void (object::*ButtonFunc)()) { BUTTON::SetButton(xPos, yPos, normalFilePath, hoverFilePath, pressedFilePath, Width, Height); this->ButtonFunc = &ButtonFunc; }
如果任何人有任何build议,我可以如何正确发送这个function,以便以后使用它。
要通过指针调用成员函数,需要两件事情:指向对象的指针和指向函数的指针。 你需要在MenuButton::SetButton()
template <class object> void MenuButton::SetButton(int xPos, int yPos, LPCWSTR normalFilePath, LPCWSTR hoverFilePath, LPCWSTR pressedFilePath, int Width, int Height, object *ButtonObj, void (object::*ButtonFunc)()) { BUTTON::SetButton(xPos, yPos, normalFilePath, hoverFilePath, pressedFilePath, Width, Height); this->ButtonObj = ButtonObj; this->ButtonFunc = ButtonFunc; }
然后你可以使用两个指针调用函数:
((ButtonObj)->*(ButtonFunc))();
不要忘记将指针传递给你的对象MenuButton::SetButton()
:
testMenu::testMenu() :MenuScreen("testMenu") { x.SetButton(100,100,TEXT("buttonNormal.png"), TEXT("buttonHover.png"), TEXT("buttonPressed.png"), 100, 40, this, test2); draw = false; }
我强烈build议boost::bind
和boost::function
的东西。
请参阅传递和调用成员函数(boost :: bind / boost :: function?)
我知道这是一个相当古老的话题。 但有一个优雅的方式来处理这与c + + 11
#include <functional>
像这样声明你的函数指针
typedef std::function<int(int,int) > Max;
声明你把这个东西传递给你的函数
void SetHandler(Max Handler);
假设你传递一个正常的函数,你可以像正常一样使用它
SetHandler(&some function);
假设你有一个成员函数
class test{ public: int GetMax(int a, int b); ... }
在你的代码中,你可以像这样使用std::placeholders
来传递它
test t; Max Handler = std::bind(&test::GetMax,&t,std::placeholders::_1,std::placeholders::_2); some object.SetHandler(Handler);
你会不会更好地使用标准的面向对象? 定义一个合约(虚拟类)并在你自己的类中实现,然后传递给你自己的类的引用,让接收者调用契约函数。
使用你的例子(我已经把'test2'方法改名为'buttonAction'):
class ButtonContract { public: virtual void buttonAction(); } class testMenu : public MenuScreen, public virtual ButtonContract { public: bool draw; MenuButton<testMenu> x; testMenu():MenuScreen("testMenu") { x.SetButton(100,100,TEXT("buttonNormal.png"), TEXT("buttonHover.png"), TEXT("buttonPressed.png"), 100, 40, &this); draw = false; } //Implementation of the ButtonContract method! void buttonAction() { draw = true; } };
在接收方法中,将引用存储到ButtonContract中,然后当您想要执行该button的操作时,只需调用该存储的ButtonContract对象的“buttonAction”方法即可。
在极less数情况下,您正在使用Borland C ++ Builder进行开发,不介意编写特定于该开发环境的代码(即不能与其他C ++编译器一起工作的代码),您可以使用__closure关键字。 我find了一篇关于C ++ Builder闭包的文章 。 它们主要用于Borland VCL。
其他人已经告诉你如何正确地做到这一点。 但是我很惊讶没有人告诉你这个代码实际上是危险的:
this->ButtonFunc = &ButtonFunc;
由于ButtonFunc是一个参数,当函数返回时它会超出范围。 你正在采取地址。 你将得到一个types为void (object::**ButtonFunc)()
( 指向成员函数的指针 ),并将其赋值给this-> ButtonFunc。 当你尝试使用this-> ButtonFunc的时候,你会尝试访问(现在不存在的)本地参数的存储,你的程序可能会崩溃。
我同意Commodore的解决scheme。 但是你必须改变他的路线
((ButtonObj)->*(ButtonFunc))();
因为ButtonObj是一个指向对象的指针 。