C++教程-C++中的函数指针
![](https://wx.javatiku.cn/j/j301-t.jpg)
C++ 中的函数指针
正如我们所知,指针用于指向变量;同样,函数指针用于指向函数。它主要用于存储函数的地址。我们可以使用函数指针调用函数,或者将函数指针作为参数传递给另一个函数。
函数指针主要用于事件驱动的应用程序、回调函数以及将函数存储在数组中等场景中非常有用。
函数的地址是什么?
计算机只能理解低级语言,即二进制形式。我们在 C++ 中编写的程序始终是高级语言,因此为了将程序转换为二进制形式,我们使用编译器。编译器是将源代码转换为可执行文件的程序。这个可执行文件存储在 RAM 中。CPU 从 main() 方法开始执行,并读取 RAM 中的副本,而不是原始文件。
所有的函数和机器代码指令都是数据。这些数据是一堆字节,所有这些字节在 RAM 中都有一些地址。函数指针包含了函数的第一条指令的 RAM 地址。
声明语法
函数指针的声明语法如下:
int (*FuncPtr) (int, int); *
上述语法是函数的声明。由于函数不像变量那样简单,但是 C++ 是类型安全的,因此函数指针具有返回类型和参数列表。在上述语法中,我们首先提供返回类型,然后是指针的名称,即 FuncPtr,它用括号括起来,并在括号之前由指针符号 (*) 修饰。之后,我们提供了参数列表 (int, int)。上述函数指针可以指向任何接受两个整数参数并返回整数类型值的函数。
函数的地址
我们可以非常容易地获得函数的地址。我们只需要提到函数的名称,无需调用函数。
让我们通过一个例子来说明。
#include <iostream>
using namespace std;
int main()
{
cout << "main() 函数的地址是:" << &main << 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 指向 add 函数
int sum = funcptr(5, 5);
cout << "sum 的值是:" << sum << endl;
return 0;
}
在上面的程序中,我们声明了函数指针 int (*funcptr)(int, int),然后将 add() 函数的地址存储在 funcptr 中。这意味着 funcptr 包含 add() 函数的地址。现在,我们可以使用 funcptr 调用 add() 函数。语句 funcptr(5, 5) 调用 add() 函数,add() 函数的结果存储在 sum 变量中。
输出结果:
sum 的值是:10 函数指针的另一个示例。
#include <iostream>
using namespace std;
void printname(char *name)
{
cout << "Name is: " << name << endl;
}
int main()
{
char s[20]; // 数组声明
void (*ptr)(char *); // 函数指针声明
ptr = printname; // 将 printname 的地址存储在 ptr 中
cout << "输入一个人的名字:" << endl;
cin >> s;
cout << s;
ptr(s); // 调用 printname() 函数
return 0;
}
在上面的程序中,我们定义了一个包含 char 指针参数的函数 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()。
输出结果: