为什么我们需要在运行时使用函数指针调用这些函数?我们也可以直接打电话给他们
why do we need to call these functions at run time using function pointers. we can as well call them directly
在阅读了一些关于函数指针和回调的内容后,我无法理解它们的基本目的。对我来说,它看起来就像不是直接调用函数,而是使用指向该函数的指针来调用它。有人能解释一下回调函数和函数指针吗?当我们使用函数指针时,为什么会发生回调,因为我们似乎只是通过指向它的指针调用函数,而不是直接调用?
感谢ps:这里有一些关于回调和函数指针的问题,但它们不能充分解释我的问题
什么是Callbak函数?
简单来说,回调函数是程序员不显式调用的函数。相反,有一些机制可以持续等待事件的发生,并且它将调用选定的函数来响应特定的事件。此机制通常用于操作(函数)可能需要很长时间才能执行,并且函数的调用者不想等待操作完成,但确实希望知道操作的结果。通常,回调函数帮助实现这样的异步机制,其中调用方注册以获得有关耗时处理和连续其他操作的结果的动画,而在稍后的时间点,调用方获得结果的通知。
一个实际的例子:
Windows事件处理:
实际上,所有的Windows程序都设置了一个事件循环,通过调用函数使程序响应特定的事件(如按钮按下,选择一个复选框,窗口获得焦点)。方便的事情是,程序员可以指定当(比如说)按下特定按钮时调用什么函数,即使不可能指定何时按下按钮。被调用的函数被称为回调函数。
一个源代码说明:
//warning: Mind compiled code, intended to illustrate the mechanism
#include <map>
typedef void (*Callback)();
std::map<int, Callback> callback_map;
void RegisterCallback(int event, Callback function)
{
callback_map[event] = function;
}
bool finished = false;
int GetNextEvent()
{
static int i = 0;
++i;
if (i == 5) finished = false;
}
void EventProcessor()
{
int event;
while (!finished)
{
event = GetNextEvent();
std::map<int, Callback>::const_iterator it = callback_map.find(event);
if (it != callback_map.end()) // if a callback is registered for event
{
Callback function = *it;
if (function)
{
(*function)();
}
else
{
std::cout << "No callback foundn";
}
}
}
}
void Cat()
{
std::cout << "Catn";
}
void Dog()
{
std::cout << "Dogn";
}
void Bird()
{
std::cout << "Birdn";
}
int main()
{
RegisterCallBack(1, Cat);
RegisterCallback(2, Dog);
RegisterCallback(3, Cat);
RegisterCallback(4, Bird);
RegisterCallback(5, Cat);
EventProcessor();
return 0;
}
上面的命令将输出如下内容:
Cat
Dog
Cat
Bird
Cat
希望这对你有帮助!
<一口>注意:这是我以前的一个答案,在这里一口>
我们需要函数指针的一个非常明显的原因是,它们允许我们调用调用代码的作者(即我们)不知道的函数!回调是一个经典的例子;qsort()
的作者不知道也不关心你如何比较元素,她只是写了一个泛型算法,由你来提供比较函数。
这里有一个简单的例子;我希望它能说服你,你不能放弃指针!
typedef int (*myfp)(); // function pointer type
const char * libname = get_library_name_from_user();
const char * funname = get_function_name_from_user();
void * libhandle = dlopen(libname, RTLD_NOW); // load the library
myfp fun = (myfp) dlsym(libhandle, funname); // get our mystery function...
const int result = myfp(); // ... and call the function
// -- we have no idea which one!
printf("Your function "%s:%s" returns %i.n", libname, funname, result);
这是为了解耦。看看sqlite3_exec()
——它接受一个回调指针,为检索到的每一行调用该指针。SQLite不关心你的回调做什么,它只需要知道如何调用它。
现在您不需要在每次回调更改时重新编译SQLite。你可以编译一次SQLite,然后重新编译你的代码,或者静态重链接,或者只是重启和动态重链接。
这也避免了名称冲突。如果你有两个库,都做排序,都希望你定义一个叫做sort_criteria
的函数,他们可以调用,你怎么用同一个函数排序2个不同的对象类型?
在sort_criteria
函数中的所有if和开关之后,它会很快变得复杂,通过回调,您可以将自己的函数(具有易于解释的名称)指定给这些排序函数。
- 当使用透明的std函数对象时,我们还需要写空的尖括号吗
- 为什么我们要为avl树实现返回一个指向节点的指针,而不是void函数
- 我们是否需要为 C++ 中的多个函数初始化多个模板?
- 为什么我们在C++中使用手动复制构造函数?
- 为什么我们使用在C++中返回数据结构的函数?
- 我们可以用参数化构造函数初始化结构的数组吗?
- C++不重载时间函数,所以我们不需要写 NULL 有什么原因吗?
- 我们如何并行运行算法的 n 个实例并以有效的方式计算结果函数的平均值?
- 我们可以有一个 setter 成员函数作为从 const 对象引用的 const 吗?
- 我们应该在使用 std::bind 应用之前检查一个不为空的函数吗?
- C++ gmock - 我们如何在单元测试 cpp 文件中读取/获取 cpp 文件函数的参数值
- JavaScript箭头函数:我们能否像C ++ lambdas一样捕获值
- 如果普通默认构造函数不执行任何操作,为什么我们不能使用 malloc 创建平凡可构造的对象?
- 我们可以在cpp中为对象分配函数吗
- 我们可以在main函数中声明嵌套类对象吗
- 为什么我们需要创建一个单参数构造函数来使用临时的无名称对象
- 为什么我们需要 & in 绑定成员函数?
- 为什么当我们使用等于'='符号比较器函数时,c ++的内置排序函数不起作用?
- Ceil函数:我们如何自己实现它
- 为什么我们需要在运行时使用函数指针调用这些函数?我们也可以直接打电话给他们