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

时间:2015-05-20 15:29:58

标签: 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;
}

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

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

TL; DR

&#34;作用&#34;和&#34;指向功能的指针&#34;是一样的。

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

概念

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

因此,如果您正在编写C语言,那么您只需要指向函数。

...然而

语法

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

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

语法稍微清晰,不涉及*符号。为了支持它,c / c ++的作者发明了&#34;衰变&#34; - 当你的代码提到&#34;一个函数&#34;时,编译器默默地&#34;纠正&#34;它意味着&#34;指向函数的指针&#34;相反(几乎在所有情况下;请原谅我没有进一步详细说明)。这非常类似于&#34;衰变&#34;一个数组到vsoftco提到的指针。

所以在你的例子中

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

&#34;功能&#34; type实际上是&#34;指向函数的指针&#34;类型。事实上,如果你试图超载&#34;:

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

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

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

runprint(add, 1);

它也无关紧要:

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

P.S。当声明一个接收回调的函数时,我主要看到(并使用过)明确写入的指针。我现在才想到,在调用回调时依赖于函数到指针的衰减是不一致的,但在声明我的代码时则不然。所以如果问题是

  

当函数语法足够时,为什么每个人都使用指向函数的语法声明回调?

我回答&#34;习惯问题&#34;。