fltk回调改变了c ++实例位置

时间:2015-07-13 21:32:22

标签: c++ pointers static callback fltk

我正在尝试创建一个包含自己的回调函数的按钮式对象(Smart_Button)。该对象是由My_Window构造函数创建的,但当我点击与地址不同的gui按钮时,其内存地址位于My_Window构造函数内部。我想启用一些需要Smart_Buttons互相指向的附加功能,但我不能,因为地址会发生变化。

奇怪的是,如果我在My_window中定义回调函数(就像我为site_parent_cb所做的那样),我会得到我期望的行为。当前程序的输出是:

site_parent_cb in constructor: 0xbfc20c6c
site_local_cb in constructor: 0xbfc20c48
(when I hit the "parent" button)
this: 0xbfc20c6c
(when I hit the "local" button)
this: 0xbfc20b90

我的代码如下。另外,我的include是调用Struoustrups编程原理和使用C ++ Book练习的文件。这些文件是某些FLTK功能的包装器,可在此处获取:http://www.stroustrup.com/Programming/PPP2code/

理解行为的任何帮助将不胜感激。我的主要问题是,如果这是关于我自己的代码,我不明白,或者它是简化的FLTK包装器的特性。

#include "GUI.h"

namespace Graph_lib {
    struct Smart_Button : Button {
    Smart_Button(Point tl, int w, int h, Callback cb);
    Smart_Button(Point tl, int w, int h);
    void print_address();
private:
    static void cb_pressed(void*, void*);
};

Smart_Button::Smart_Button(Point tl, int w, int h, Callback cb)
    :Button(tl, w, h, "parent", cb)
{
}

Smart_Button::Smart_Button(Point tl, int w, int h)
    :Button(tl, w, h, "local", cb_pressed)
{
}

void Smart_Button::cb_pressed (void*, void* pw){static_cast<Smart_Button*>(pw)->print_address();}

void Smart_Button::print_address(){
    cout << "this: " << this << endl;
}


struct My_Window : Window {
    My_Window();
    Smart_Button site_local_cb;
    Smart_Button site_parent_cb;
private:
    static void cb_pressed(void*, void*);
};

My_Window::My_Window()
    :Window(Point(100,100),200,200,"Some App"),
    site_parent_cb(Point( 50, 50), 40, 40, cb_pressed),
    site_local_cb(Point(100, 50), 40, 40)
{   
    cout << "site_parent_cb in constructor: " << &site_parent_cb << endl;
    cout << "site_local_cb in constructor: " << &site_local_cb << endl;
    attach(site_parent_cb);
    attach(site_local_cb);
}

void My_Window::cb_pressed (void*, void* pw){static_cast<My_Window>(pw)->site_parent_cb.print_address();}
};


int main(int argc, char **argv) {
    using namespace Graph_lib;
    My_Window game;
    return gui_main();
}

1 个答案:

答案 0 :(得分:0)

问题在于回调

void My_Window::cb_pressed (void*, void* pw)
{
    static_cast<My_Window>(pw)->site_parent_cb.print_address();
}

设置回调时,传入的参数是Smart_Button的地址。按下该按钮时,回调将参数转换为My_Window并获取site_parent_cb的偏移量,该偏移量恰好与My_Window的地址相差4个字节。这就是为什么地址不一致的原因。回调应该是

void My_Window::cb_pressed(void*, void* pw)
{
    static_cast<Smart_Button*>(pw)->print_address()
}

这是一个非常好的收获。如果交换了本地和父母的职位,那么就不会发现差异。