传入并存储对象

时间:2015-12-23 12:55:58

标签: c++ pointers function-pointers

我正在编写一个基本的GUI框架作为学校项目,并且我试图创建一个对象(想象一个按钮),当与之交互时,它将调用特定的函数。

为了简单解释我的设置,我有一个按钮类和一个窗口管理器类。窗口管理器从main实例化一次,许多按钮从窗口管理器实例化,所有3个按钮都在单独的文件中。什么都不应该进入主。

我有点像C ++ noob,但据我所知,最好使用函数指针。我的想法是实例化我的按钮对象,然后将一个函数指针传递给一个函数,该函数在被调用时会编辑另一个对象。

首先,我认为最好的方法是将功能本地定义到窗口管理器,否则我会遇到访问问题?我本来想最初没有在标题中列出它们以使事情变得更容易(为了将来创建一种拖放编辑器)。

其次,我如何将(从窗口管理器)指向函数(存在于窗口管理器中)的指针传递给按钮对象的实例?我以为我能够像对待任何其他变量一样对待它并做一些事情:

Button btn1 = new Button();
btn1->SetText("Button 1");
btn1->SetOnClick(functionpointer);

但是,在浏览了各种教程之后,我并不完全理解我是如何实现这一点的。例如,我如何定义某个地方将函数指针存储在我的按钮类中?

感谢任何见解,我想我有一天会把自己弄糊涂了。

编辑:似乎我应该添加我的ButtonWindowManager类在不同的文件中,我的入口点可以说是WindowManager的一个实例。我的GUI的所有设置,包括为按钮分配功能都将在WindowManager的构造函数中完成。

2 个答案:

答案 0 :(得分:3)

这是一种使用函数指针的方法。但是,使用std::function可以使代码更加灵活。例如,您可以使用lambda表达式。 要使用std::function,您只需将typedef更改为typedef std::function<void(Button*)> EventCallback;并添加包含#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;
}

http://ideone.com/x5O49B

答案 1 :(得分:2)

你可以用这样的成员函数指针(在这种情况下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中使用typdef而不是WindowManager ...

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 );