类型转换/回调函数

时间:2015-02-06 15:59:22

标签: c++

我目前正在尝试使用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}}

2 个答案:

答案 0 :(得分:6)

(T)a - 样式转换,也称为C样式转换,它实际上是最差方式在C ++中进行显式转换。这是因为它是最强大的 - 它会愉快地转换几乎任何东西,轻松隐藏严重错误。它是C中唯一可用的显式类型转换形式,它由C ++继承,但绝不应该用于高质量的C ++代码。

wordvoid*的强制转换是不必要的 - 任何指向对象类型的指针都可以隐式转换为指向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());