我目前正在尝试使用FLTK GUI库,但我不确定回调函数是怎么回事 - 特别是类型转换对我来说有点陌生。下面的示例显示了一个基本窗口,其中有一个标有“Press”的按钮。当您按下按钮时,标签会变为“完成”。
传递给回调函数的标签被声明为类型const char*
,然后它被强制转换为void*
类型,但是可以将其声明为std::string
然后施放到void*
?我更喜欢使用现代C ++字符串而不是char
符号。
此外,语法是否是从一种类型转换为另一种类型的最佳方式?我之前看到static_cast<type>()
使用了const char*
从void*
到#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Native_File_Chooser.H>
#include <string>
void xyz_callback(Fl_Widget* w, void* userdata)
{
Fl_Button* b = (Fl_Button*)w; //cast widget w to button and assign to b
b->label((const char*)userdata); //cast userdata back to type const char*
}
int main(int argc, char **argv)
{
Fl_Window *window = new Fl_Window(340,180);
Fl_Button *button = new Fl_Button(20,40,300,100, "label");
button->label("Press");
button->labelfont(FL_BOLD+FL_ITALIC);
button->labelsize(36);
button->labeltype(FL_SHADOW_LABEL);
button->when(FL_WHEN_RELEASE);
const char* word = "Done";
button->callback(xyz_callback, (void*)word); //cast word to type void*
window->end();
window->show(argc, argv);
return Fl::run();
}
的最安全/最佳方式,反之亦然?为什么? C ++ 11会推荐什么?
{{1}}
答案 0 :(得分:6)
(T)a
- 样式转换,也称为C样式转换,它实际上是最差方式在C ++中进行显式转换。这是因为它是最强大的 - 它会愉快地转换几乎任何东西,轻松隐藏严重错误。它是C中唯一可用的显式类型转换形式,它由C ++继承,但绝不应该用于高质量的C ++代码。
word
到void*
的强制转换是不必要的 - 任何指向对象类型的指针都可以隐式转换为指向void
的指针。
在回调中转换回const char*
是必要的,但可以使用static_cast<const char*>(userdata)
完成。
解决有关std::string
的问题:这取决于生命周期。您可以将std::string*
转换为void*
并将其传递给回调。在那里,您将其转回str::string*
(然后从中检索c_str()
以传递给label
函数。但是,在调用回调时,您必须确保指向的std::string
仍处于活动状态(没有超出范围)。如果您在main
中将其设为局部变量,那么您将非常安全。
如果你这样做,代码将如下所示:
void xyz_callback(Fl_Widget* w, void* userdata)
{
Fl_Button* b = static_cast<Fl_Button*>(w);
b->label(static_cast<std::string*>(userdata)->c_str());
}
int main(int argc, char **argv)
{
Fl_Window *window = new Fl_Window(340,180);
Fl_Button *button = new Fl_Button(20,40,300,100, "label");
button->label("Press");
button->labelfont(FL_BOLD+FL_ITALIC);
button->labelsize(36);
button->labeltype(FL_SHADOW_LABEL);
button->when(FL_WHEN_RELEASE);
std::string word = "Done";
button->callback(xyz_callback, &word);
window->end();
window->show(argc, argv);
return Fl::run();
}
答案 1 :(得分:0)
如果你的回调期望void*
,那么你可以将指针传递给任何东西。但是回调必须知道如何处理这个参数。它必须将其强制转换为可用的类型。
您可以更改回调,以便指向指向std::string
的指针。如果你想在回调中有const char*
,你必须将C风格的字符串传递给回调:
button->callback(xyz_callback, str.c_str());