c++ - 为什么必须使用函数指针?

标签 c++ pointers function-pointers

什么需要函数指针?这个问题的标准答案似乎是回调,但为什么我们不能只传递一个函数呢?

我正在阅读的关于 C++ 的书演示了将函数作为参数传递,并承认实际上编译将其转换为函数指针并传递它,因为函数不是实际对象。它显示了使用函数指针的等效代码,这稍微复杂一些 - 如果代码是等效的,为什么还要费心使用函数指针。

我假设有一种情况根本不可能传递函数,而必须传递一个指针?谁能给我一个这种情况的例子,因为它会帮助我理解为什么函数指针很有用。

考虑以下代码:

#include <iostream>

using namespace std;

int add(int x) {
        return ++x; //this is a copy, so it doesn't touch x
}

void runprint(int function(int x), int x) {
        cout << function(x) << endl;
}


int main() {
        runprint(add, 1);

        return 0;
}

我们将函数作为参数传递,而不是指针。接受函数 (!) 的函数不接受指针。

最佳答案

TL;博士

“函数”和“指向函数的指针”是一样的。


有指针的概念,以及它的使用语法;不清楚你在问什么。

概念

指向函数的指针可能与函数本身不同(区别在 c++ 中没有用 - 见下文)因为函数可能占用很多空间 - 它的代码可以任意复杂。操作(例如复制或搜索/修改)函数的代码很少有用,因此 c/c++ 根本不支持它。如果你想修改函数的代码,将指针转换为 char*,应用所有必要的预防措施(我从未这样做过)。

因此,如果您正在编写 C,您所需要的只是指向函数的指针。

然而...

语法

如果你有一个指向函数的指针p,你想如何调用这个函数?

(*p)(18); // call the function with parameter 18
p(18); // the same, but looks better!

有不涉及 * 符号的更简洁的语法。为了支持它,c/c++ 的作者发明了“衰减”的概念——当你的代码提到“一个函数”时,编译器会默默地“更正”它的意思是“一个指向函数的指针”(几乎在所有情况下;请原谅我没有进一步详细说明)。这与 vsoftco 提到的数组“衰减”到指针非常相似。

所以在你的例子中

void runprint(int function(int x), int x) {
        cout << function(x) << endl;
}

“函数”类型实际上是“指向函数的指针”类型。实际上,如果您尝试“重载”:

void runprint(int (*function)(int x), int x) {
        cout << function(x) << endl;
}

编译器会提示两个具有相同参数集的相同函数。

此外,在创建函数/函数指针类型的变量时

runprint(add, 1);

也没关系:

runprint(&add, 1); // does exactly the same

附言在声明接收回调的函数时,我大多看到(并使用)了显式编写的指针。我现在才想到,在调用回调时依赖函数到指针的衰减是不一致的,但在声明我的代码时却不是。所以如果问题是

why does everyone declare callbacks using a pointer-to-function syntax, when a function syntax would be sufficient?

我会回答“习惯问题”。

关于c++ - 为什么必须使用函数指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30354108/

相关文章:

python - Python变量是指针吗?否则,它们是什么?

c++ - 删除指向对象的指针会导致 Break

c++ - 如何将指针传递给模板类的成员函数?

c++ - 使用函数指针有什么好处?

c++ - 读写竞争条件会改变同时读取和写入的数据吗?

c++ - 无法理解这个 "message sequence mismatch error"

iphone - 什么时候写“NSString * str”或“NSString str”?

c - 获取除 void * 之外的不兼容指针类型警告

c++按值或指向函数语法的指针传递数组

c++ - 基于 bool 模板参数的重载