如何使用atexit()注册非void函数?

时间:2015-02-14 14:07:36

标签: c++ c ncurses atexit

我正在尝试使用int函数注册一个返回atexit()的函数,该函数将在程序结束时调用。 (具体来说,来自ncurses的endwin()函数。)

但由于atexit()需要一个指向void函数的指针,我遇到了一个问题。我尝试了以下方法:

static_cast<void (*)()>(endwin)

但似乎不允许static_castint函数转换为void函数。

我想要完成的是什么,如果是的话,怎么样?

注意:我愿意忽略该函数的返回值。


编辑:我也尝试过创建一个lambda函数,它似乎可以做我想要的:

atexit([]{ endwin(); });

与包装/转发功能相比,这是一个很好的解决方案吗? (除此之外,它需要C ++ 11并避免定义一个新功能,其唯一目的是转发另一个功能。)

3 个答案:

答案 0 :(得分:23)

无法转换函数指针。只需注册一个转发功能:

#ifdef __cplusplus
extern "C"
#endif
void endwin_wrapper() { endwin(); }
...
atexit(endwin_wrapper);

由于您标记了问题C ++:如果您在C ++中定义转发函数,则需要将其声明为extern "C"以使其具有正确的语言链接。

答案 1 :(得分:11)

使用当前的C ++标准,lambda可能是最佳解决方案:

atexit([]{ endwin(); });

现在没有必要定义一个全新的命名函数,其唯一目的只是转发另一个函数。


如果有一天你决定需要在程序退出时调用更多函数,你可以通过对atexit()的新调用来定义它们:

atexit(anotherCleanupFunction);

或者,你可以将它们添加到lambda体中:

atexit([]{
  anotherCleanupFunction();
  endwin();
});

但是,当你有多个函数要注册atexit()时,一个单独的包装函数来保存所有这些函数可能是一个更好的解决方案。但是没有一个正确的答案,只需编写好的和清晰的代码。 (通过充满函数调用的lambda调用atexit()可能看起来很混乱。)

答案 2 :(得分:6)

  

“我想要完成的是什么,如果是的话,怎么样?”

您只需为endwin()编写自己的包装函数并注册该函数

void myEndwin() {
    endwin();
}