首页 > 解决方案 > 在 C++ 中使用回调

问题描述

我正在使用 C++ 开发一个项目,但在应用程序的某个时刻它失败并生成核心转储。该应用程序使用了几个类,出于此处的目的,我将重点放在其中一个类上,我将其称为 A,并将其实例化为对象 a。这有大量的成员函数,目前只使用其中的几个,但其中一个会生成一个日志以生成用于调试的诊断信息。我想用它来找出应用程序失败的原因。

该项目是将调用各种成员函数的代码放在一起,虽然我可以访问源代码和一些有限的文档,但没有任何代码可以更改,所有更改都在使用类和的代码中调用成员函数。有问题的成员函数是:

void enable_log (log_callback callback, void * user_data = nullptr)

其中第一个参数回调包含消息,第二个参数是可选的。现在它可以设置为 nullptr,所以会被调用为:

a.enable_log(callback, nullptr);

从这个文档中,完全不清楚回调到底是什么。但是,在查看源代码时,这是:

using log_callback = void (*)(const std::string& message, void* user_data);

在头文件中,如果我理解正确的话,log_callback 是 const std::string& 的别名。

我已经在使用 Visual Studio 2019 的平台上拥有虚拟类,并带有一些测试成员函数来模拟在远程 Linux 服务器上调用成员函数,但我无法找到利用上述成员函数的方法。我将测试成员函数添加到虚拟类中,如下所示:

void enable_log(const std::string& callback, void* user_data = nullptr) {
    callback = "ABCD";
}

它应该生成一个返回的测试字符串,这样在实际应用程序中,该字符串将具有将写入文件的诊断信息。但是,“=”是一个错误。

这个想法是在主函数中声明一个空字符串,然后 enable_log() 应该填充这个字符串,可以打印出来。

我花了一些时间查看各种资源,包括 Stackoverflow,但我找不到返回带有可打印信息的字符串的方法。我需要一个简单的方法来模拟这个,正如我上面所说的,我不能改变真实成员函数的源代码,所以模拟的成员函数必须以相同的方式产生一个字符串。这是怎么做到的?一些建议将不胜感激。

标签: c++classcallback

解决方案


简单来说,回调是稍后将在某个时候调用的某个函数。例子:

void callback_fn(int a);

using callback_t = (void)(*)(int a);
void some_func(callback_t);

你可以some_func()这样使用:

some_func(callback_fn);

完整示例:https ://godbolt.org/z/ET3GhfYrv

对于您的用例,回调的参数略有不同。以下是阅读语法的方法:

using log_callback = // this just creates an alias for whatever is on the right handside

void // the return type of the "callable" should be void

(*) // this tells us that it is a function pointer

(const std::string& message, void* user_data) // These are the arguments the callable takes. It is a "std::string" and a "void *"

要使用它,只需创建一个具有相同签名的自由函数:

void callable(const std::string &msg, void *userData = nullptr)
{
   // msg is the data sent by the function. use it in whatever way
   // you want.
   std::cout << msg << '\n';
}

// Pass it to the enable_log
enable_log(callable);

推荐阅读