【发布时间】:2019-10-02 01:11:39
【问题描述】:
为了更容易解释,我已经简化了我的示例。我正在编写一个计数为 100 的应用程序,但在任何给定时间,我都允许用户通过键盘输入 ctrl+c 来取消该程序。
由于我对函数指针缺乏了解,最初看似简单的程序很快变得复杂起来。这就是我正在尝试做的:
- 按下
ctrl+c时捕获SIGINT信号。 - 捕获后,调用一个成员函数来关闭第三方资源。
问题在于,与Michael Haidl 和Grijesh Chauhan 给出的捕获SIGINT 的两个示例不同,我不允许存储任何全局变量。理想的情况是,与signal() 相关的所有变量和函数调用都封装在我的一个类中。
这是我基于 Haidl 和 Grijesh 的 代码的修改尝试:
#include <thread>
#include <chrono>
#include <functional>
#include <iostream>
#include <signal.h>
class MyClass {
public:
volatile sig_atomic_t cancel = 0;
void sig_handler(int signal) {
cancel = true;
this->libCancel();
}
void libCancel() { std::cout << "Cancel and cleanup" << std::endl; }
};
int main(int argc, char *argv[]) {
MyClass mc;
//using std::placeholders::_1;
//std::function<void(int)> handler = std::bind(&MyClass::sig_handler, mc, _1);
//signal(SIGINT, handler);
signal(SIGINT, &mc.sig_handler); // **compiler error**
for (int i = 0; !mc.cancel && i < 100; ++i)
{
std::cout << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
如您所见,我希望代码简单地数到 100 并在一切顺利时退出。但是如果用户调用ctrl+c,那么该类应该处理SIGINT,调用外部库进行清理,for 循环将退出。
主要问题是我似乎无法设置signal() 声明来绑定到我的MyClass::sig_handler 实例。我什至尝试将我的成员函数转换为 std::function 以供 signal() 使用,注释掉了,但编译器对 C++ function<void(int)> 不等同于 C 语言 void (*)(int) 的事实并不满意。
欢迎任何批评。我完全不依赖于我所写的内容,而且对于如何将函数指针与成员函数一起使用,我显然没有很好的基本理解。
【问题讨论】:
-
信号句柄是全局的。如果
MyClass的实例不止一个,您希望它如何运行? -
好点,
MyClass可能只有一个实例,这是否意味着我可以简单地将sig_handler设为静态? -
是的,并且有一个全局指针指向您拥有的唯一
MyClass实例。这也提出了一个问题,为什么你首先需要它成为一个类。 -
你不能获取非静态成员函数的地址,因为你不能在没有类的特定实例的情况下调用非静态成员函数。有关更多解释,请参阅指向成员函数的指针(尽管您也不能将 PTMF 用作 C 回调)。您可以使用静态成员函数,尽管这在道德上等同于全局变量。
-
是否允许使用静态类变量?它们具有全局生命周期,如果不是全局范围的话。
标签: c++ c lambda function-pointers sigint