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

Why must function pointers be used?

函数指针需要什么?标准答案好像是回调,但是为什么不能只传一个函数呢?

我正在阅读的关于 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;
}

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

function 被 g++ 认为是一个函数指针:

$ cat fp.cpp
#include <typeinfo>
#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 << typeid(function).name() << endl;
        int (*f)(int);  // function pointer compatible with function argument
        f = function;
        cout << typeid(f).name() << endl;
        cout << function(x) << endl;
}


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

        return 0;
}
$ g++ -Wall -std=c++11 -o fp fp.cpp
$ ./fp
PFiiE
PFiiE
2

TL;博士

"Function"和"pointer to function"是一样的。


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

概念

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

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

然而...

语法

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

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

语法稍微简洁一些,不涉及 * 符号。为了支持它,c/c++ 的作者发明了 "decay" 的概念 - 当您的代码提到 "a function" 时,编译器会默默地 "corrects" 表示 "a pointer to a function"相反(在几乎所有情况下;请原谅我没有进一步详细说明)。这与 vsoftco 提到的 "decay" of an array to a pointer 非常相似。

所以在你的例子中

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

"function"类型实际上是"pointer to function"类型。实际上,如果您尝试 "overload":

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

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

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

runprint(add, 1);

也没关系:

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

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

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

我会回答 "a matter of habit"。

函数指针是保存函数地址的指针。 函数指针是在不知道函数名的情况下调用函数。这对于在运行时使用不同的功能很实用。