简介
函数的二进制代码存放在内存四区中的代码区,函数的地址是它在内存中的起始地址。如果把函数的地址作为参数传递给函数,就可以在函数中灵活的调用其它函数。
使用函数指针的三个步骤:
1.声明函数指针:
声明普通指针时,必须提供指针的类型。同样,声明函数指针时,也必须提供函数类型,函数的类型是指返回值和参数列表(函数名和形参名不是)
函数之间具有相同的返回值类型和参数列表数目和类型都相同即是同一类函数
1.1声明函数指针语法
函数的返回值类型 (*自定义指针名字) (函数形参列表可写名字也可以不写)
#include <iostream> using namespace std; void eat_ming(string food1) { cout << "小明吃" << food1 << endl; } void eat_hong(string food2) { cout << "小红吃饭" << food2 << endl; } int main() { //声明函数指针 void (*ming_hong_ptr)(string); ming_hong_ptr = eat_ming; //调用 ming_hong_ptr("香蕉"); (*ming_hong_ptr)("香蕉"); // 用函数指针名调用函数。 C语言 ming_hong_ptr = eat_hong; ming_hong_ptr("苹果"); (*ming_hong_ptr)("苹果"); // 用函数指针名调用函数。 C语言 return 0; }
2.让函数指针指向函数的地址:
2.1语法:
void (*ming_hong_ptr)(string); ming_hong_ptr = eat_ming;
2.2注意在QT中的connect函数中,你可能看见这种写法(&func)对函数取地址:
func函数原型:
void func() { cout << "dfa"; }
按照&运算符本来的意义,它要求其操作数是一个对象,但函数名不是对象(函数是一个对象),本来&func是非法的,但很久以前有些编译器已经允许这样做, c/c++标准的制定者出于对象的概念已经有所发展的缘故,也承认了&func的合法性。
因此,对于func和&func你应该这样理解,func是函数的首地址,它的类型是void (),&func表示一个指向函数func这个对象的地址, 它的类型是void (*)(),因此func和&func所代表的地址值是一样的,但类型不一样。
其实这种写法就跟数组一样,假设有一数组a100]那么a就代表数组的首地址,&a是整个数组的地址。他们的意义不一样。
总的来说,在绝大多数情况下,对函数取地址和直接写函数名在使用上并没有太大的区别。C++ 编译器通常会自动将函数名转换为函数指针类型,以适应上下文。不过在一些特殊的情况下,如明确需要函数指针类型或者在模板编程中,你可能需要注意这些微妙的差别。
3.通过函数指针调用函数。
//调用 ming_hong_ptr("香蕉"); (*ming_hong_ptr)("香蕉"); // 用函数指针名调用函数。 C语言 ming_hong_ptr = eat_hong; ming_hong_ptr("苹果"); (*ming_hong_ptr)("苹果"); // 用函数指针名调用函数。 C语言
回调函数
现有一个饭店小明和小红还有很多不知名的客人,我们不可能用一个函数封装起来它的所有操作,只能封装起开他们的共同操作
例代码:
#include <iostream> using namespace std; void eat( string name, string food1) { cout << name << "吃" << food1 << endl; } void fan_dian() { cout << "点餐" << endl; cout << "做饭" << endl; eat("某某", "某某食物"); } int main() { fan_dian() return 0; }
在以上代码中我们就只能封装他们的共同性,可是他们的个人习惯也不能没有啊。
此时函数指针就有用了
例代码:
#include <iostream> using namespace std; void eat_ming(string food1, int spending_power = 0) { cout << "小明吃" << food1 << endl; cout << "小明站在凳子上吃" << endl; } void eat_hong(string food2,int spending_power = 0 ) { cout << "小红吃饭" << food2 << endl; cout << "小红站在桌子上吃" << endl; } void fan_dian(void (*habit)(string,int)) { cout << "点餐" << endl; cout << "做饭" << endl; habit("香蕉",59); //缺省值没有用,函数指针写有几个参数就要传入几个参数 } int main() { void (*habit)(string,int); habit = eat_ming; fan_dian(habit); habit = eat_hong; fan_dian(habit); return 0; }
利用函数指针当形参可以传入你想要的客人习惯