传入函数指针并将其存储到 object
Pass in and store function pointer to object
我正在编写一个基本的 GUI 框架作为一个学校项目,我正在尝试创建一个 object(想想一个按钮),当与之交互时,将调用一个特定的函数。
为了简单说明我的设置,我有一个按钮 class 和一个 window 管理器 class。 window 管理器从 main 实例化一次,许多按钮从 window 管理器实例化,所有 3 个都在单独的文件中。什么都不应该放在 main.
我有点 C++ 菜鸟,但据我所知,最好为此使用函数指针。我的想法是实例化我的按钮 object 然后将一个函数指针传递给一个函数,该函数在被调用时会编辑另一个 object.
首先,我认为最好的方法是在 window 管理器本地定义函数,否则我在访问时会遇到问题?我最初不想将它们列在 header 中以使事情变得更容易(以期在将来创建一种拖放编辑器)。
其次,我如何将(从 window 管理器)指向函数(存在于 window 管理器中)的指针传递给按钮的实例 object ?我认为我可以像对待任何其他变量一样对待它并做一些事情:
Button btn1 = new Button();
btn1->SetText("Button 1");
btn1->SetOnClick(functionpointer);
但是,在浏览了各种教程之后,我不太明白如何实现它。例如,我什至如何定义某个地方来存储我的按钮中的函数指针 class?
非常感谢任何见解,我想我已经把自己搞糊涂了一天。
编辑:似乎我应该补充一点,我的 Button
和 WindowManager
classes 在不同的文件中,我的入口点可以说是一个实例WindowManager
。我的 GUI 的所有设置,包括为按钮分配功能,都将在 WindowManager
.
的构造函数中完成
这是一种使用函数指针的方法。但是使用 std::function
使代码更加灵活。例如,您可以使用 lambda 表达式。
要使用 std::function
,您只需将 typedef 更改为 typedef std::function<void(Button*)> EventCallback;
并添加 include #include <functional>
#include <iostream>
class Button
{
public:
// Typedef of the event function signature
typedef void(*EventCallback)(Button* button);
Button() : onClick(nullptr) {}
// Set the function to call
void SetOnClick(EventCallback func) { onClick = func; }
// Call the function if exists
void OnClick() {
if (onClick)
onClick(this);
}
private:
// This stores the function pointer for the button
EventCallback onClick;
};
// just some example function that has the same signature as Button::EventCallback
void MyEventFunc(Button* button)
{
std::cout << "Triggered" << std::endl;
}
int main() {
Button button;
button.SetOnClick(&MyEventFunc);
button.OnClick();
return 0;
}
您可以像这样使用指向成员函数的指针来完成(在这种情况下,Button 必须知道 WindowManager);
class WindowManager
{
public:
typedef void (WindowManager::* TypeOnClickFunc)( void );
void anyfunction( void ) {}
};
class Button
{
public:
Button( WindowManager * wm ) :_windowmanager( wm ) {}
void SetOnClick( WindowManager::TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(_windowmanager->*_onclickfptr )( ); // indirect call WindowManager::anyfunction
}
private:
WindowManager *_windowmanager;
WindowManager::TypeOnClickFunc _onclickfptr;
};
WindowManager wm;
Button *btn1 = new Button( &wm );
btn1->SetOnClick( &WindowManager::anyfunction );
...或像这样指向静态函数的指针...
class WindowManager
{
public:
typedef void (*TypeOnClickFunc)( void );
static void anyfunction( void ) {}
};
class Button
{
public:
Button() {}
void SetOnClick( WindowManager::TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(*_onclickfptr )( ); // indirect call static WindowManager::anyfunction
}
private:
WindowManager::TypeOnClickFunc _onclickfptr;
};
Button *btn1 = new Button();
btn1->SetOnClick( &WindowManager::anyfunction );
...在 Button 而不是 WindowManager 中使用 typdef ...
class WindowManager
{
public:
static void anyfunction( void ) {}
};
class Button
{
public:
typedef void (*TypeOnClickFunc)( void );
Button() {}
void SetOnClick( TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(*_onclickfptr )( ); // indirect call
}
private:
TypeOnClickFunc _onclickfptr;
};
Button *btn1 = new Button();
btn1->SetOnClick( &WindowManager::anyfunction );
我正在编写一个基本的 GUI 框架作为一个学校项目,我正在尝试创建一个 object(想想一个按钮),当与之交互时,将调用一个特定的函数。
为了简单说明我的设置,我有一个按钮 class 和一个 window 管理器 class。 window 管理器从 main 实例化一次,许多按钮从 window 管理器实例化,所有 3 个都在单独的文件中。什么都不应该放在 main.
我有点 C++ 菜鸟,但据我所知,最好为此使用函数指针。我的想法是实例化我的按钮 object 然后将一个函数指针传递给一个函数,该函数在被调用时会编辑另一个 object.
首先,我认为最好的方法是在 window 管理器本地定义函数,否则我在访问时会遇到问题?我最初不想将它们列在 header 中以使事情变得更容易(以期在将来创建一种拖放编辑器)。
其次,我如何将(从 window 管理器)指向函数(存在于 window 管理器中)的指针传递给按钮的实例 object ?我认为我可以像对待任何其他变量一样对待它并做一些事情:
Button btn1 = new Button();
btn1->SetText("Button 1");
btn1->SetOnClick(functionpointer);
但是,在浏览了各种教程之后,我不太明白如何实现它。例如,我什至如何定义某个地方来存储我的按钮中的函数指针 class?
非常感谢任何见解,我想我已经把自己搞糊涂了一天。
编辑:似乎我应该补充一点,我的 Button
和 WindowManager
classes 在不同的文件中,我的入口点可以说是一个实例WindowManager
。我的 GUI 的所有设置,包括为按钮分配功能,都将在 WindowManager
.
这是一种使用函数指针的方法。但是使用 std::function
使代码更加灵活。例如,您可以使用 lambda 表达式。
要使用 std::function
,您只需将 typedef 更改为 typedef std::function<void(Button*)> EventCallback;
并添加 include #include <functional>
#include <iostream>
class Button
{
public:
// Typedef of the event function signature
typedef void(*EventCallback)(Button* button);
Button() : onClick(nullptr) {}
// Set the function to call
void SetOnClick(EventCallback func) { onClick = func; }
// Call the function if exists
void OnClick() {
if (onClick)
onClick(this);
}
private:
// This stores the function pointer for the button
EventCallback onClick;
};
// just some example function that has the same signature as Button::EventCallback
void MyEventFunc(Button* button)
{
std::cout << "Triggered" << std::endl;
}
int main() {
Button button;
button.SetOnClick(&MyEventFunc);
button.OnClick();
return 0;
}
您可以像这样使用指向成员函数的指针来完成(在这种情况下,Button 必须知道 WindowManager);
class WindowManager
{
public:
typedef void (WindowManager::* TypeOnClickFunc)( void );
void anyfunction( void ) {}
};
class Button
{
public:
Button( WindowManager * wm ) :_windowmanager( wm ) {}
void SetOnClick( WindowManager::TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(_windowmanager->*_onclickfptr )( ); // indirect call WindowManager::anyfunction
}
private:
WindowManager *_windowmanager;
WindowManager::TypeOnClickFunc _onclickfptr;
};
WindowManager wm;
Button *btn1 = new Button( &wm );
btn1->SetOnClick( &WindowManager::anyfunction );
...或像这样指向静态函数的指针...
class WindowManager
{
public:
typedef void (*TypeOnClickFunc)( void );
static void anyfunction( void ) {}
};
class Button
{
public:
Button() {}
void SetOnClick( WindowManager::TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(*_onclickfptr )( ); // indirect call static WindowManager::anyfunction
}
private:
WindowManager::TypeOnClickFunc _onclickfptr;
};
Button *btn1 = new Button();
btn1->SetOnClick( &WindowManager::anyfunction );
...在 Button 而不是 WindowManager 中使用 typdef ...
class WindowManager
{
public:
static void anyfunction( void ) {}
};
class Button
{
public:
typedef void (*TypeOnClickFunc)( void );
Button() {}
void SetOnClick( TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(*_onclickfptr )( ); // indirect call
}
private:
TypeOnClickFunc _onclickfptr;
};
Button *btn1 = new Button();
btn1->SetOnClick( &WindowManager::anyfunction );