众所周知,指针用于指向一些变量;同样,函数指针是用来指向函数的指针。它基本上用于存储函数的地址。我们可以使用函数指针来调用函数,也可以将指针作为参数传递给另一个函数。
它们主要用于事件驱动的应用程序、回调,甚至用于将函数存储在数组中。
计算机只能理解低级语言,即二进制形式。我们用C++写的程序总是高级语言,所以要将程序转换成二进制形式,就要用到编译器。编译器是将源代码转换为可执行文件的程序。该可执行文件存储在 RAM 中。CPU 从 main() 方法开始执行,它读取 RAM 中的副本而不是原始文件。
所有的功能和机器代码指令都是数据。这个数据是一堆字节,所有这些字节在 RAM 中都有一些地址。函数指针包含函数的第一条指令的 RAM 地址。
以下是函数指针声明的语法:
int (*FuncPtr) (int,int);
上面的语法是函数声明。由于函数不像变量那么简单,而C++是类型安全的,所以函数指针有返回类型和参数列表。在上面的语法中,我们首先提供返回类型,然后是指针的名称,即 FuncPtr,它被方括号括起来,前面是指针符号,即 (*)。在此之后,我们提供了参数列表(int,int)。上面的函数指针可以指向任何接受两个整型参数并返回整型值的函数。
我们可以很容易地得到一个函数的地址。我们只需要提到函数的名称,我们不需要调用函数。
让我们通过一个例子来说明。
#include <iostream> using namespace std; int main() { std::cout << "main() 函数的地址是:" <<&main<< std::endl; return 0; }
在上面的程序中,我们显示了 main() 函数的地址。要打印 main() 函数的地址,我们刚刚提到了函数的名称,没有括号没有参数。因此,没有任何括号或参数的函数名称本身就是函数的地址。
我们可以使用另一种方法来打印函数的地址,即&main。
我们可以通过简单地使用函数指针的名称在函数指针的帮助下调用函数。通过函数指针调用函数的语法与我们正常调用函数的语法类似。
让我们通过一个例子来理解这个场景。
#include <iostream> using namespace std; int add(int a , int b) { return a+b; } int main() { int (*funcptr)(int,int); // 函数指针声明 funcptr=add; // funcptr 指向添加函数 int sum=funcptr(5,5); std::cout << "总和的值为:" <<sum<< std::endl; return 0; }
在上面的程序中,我们声明了函数指针,即int (*funcptr)(int,int),然后将add() 函数的地址存储在funcptr 中。这意味着 funcptr 包含 add() 函数的地址。现在,我们可以使用 funcptr 调用 add() 函数。语句 funcptr(5,5) 调用 add() 函数,add() 函数的结果存储在 sum 变量中。
输出:
让我们看另一个函数指针的例子。
#include <iostream> using namespace std; void printname(char *name) { std::cout << "名称是:" <<name<< std::endl; } int main() { char s[20]; // 数组声明 void (*ptr)(char*); // 函数指针声明 ptr=printname; // 在 ptr 中存储 printname 的地址。 std::cout << "请输入人员姓名:" << std::endl; cin>>s; cout<<s; ptr(s); // 调用 printname() 函数 return 0; }
在上面的程序中,我们定义了包含字符指针作为参数的函数 printname()。我们声明函数指针,即void (*ptr)(char*)。语句 ptr=printname 表示我们将 printname() 函数的地址分配给 ptr。现在,我们可以使用语句 ptr(s) 来调用 printname() 函数。
输出:
函数指针可以作为参数传递给另一个函数。
让我们通过一个例子来理解。
#include <iostream> using namespace std; void func1() { cout<<"调用了 func1"; } void func2(void (*funcptr)()) { funcptr(); } int main() { func2(func1); return 0; }
在上面的代码中,func2() 函数将函数指针作为参数。main() 方法调用 func2() 函数,其中传递了 func1() 的地址。这样,func2() 函数间接调用了 func1()。
输出: