函数指针和回调函数对函数取地址和直接使用函数名的差距

简介: 函数指针和回调函数对函数取地址和直接使用函数名的差距

简介

函数的二进制代码存放在内存四区中的代码区,函数的地址是它在内存中的起始地址。如果把函数的地址作为参数传递给函数,就可以在函数中灵活的调用其它函数。

使用函数指针的三个步骤:

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;
}

利用函数指针当形参可以传入你想要的客人习惯

目录
相关文章
|
24天前
|
存储 C语言 C++
如何通过指针作为函数参数来实现函数的返回多个值
在C语言中,可以通过将指针作为函数参数来实现函数返回多个值。调用函数时,传递变量的地址,函数内部通过修改指针所指向的内存来改变原变量的值,从而实现多值返回。
|
1月前
链表指针的传参,传值和传地址
本文讨论了链表操作中指针传参的问题,特别是指针的传值与传地址的区别,并提供了修正代码,以确保链表插入操作能正确地修改指针指向的地址。
16 1
链表指针的传参,传值和传地址
|
24天前
|
存储 搜索推荐 C语言
如何理解指针作为函数参数的输入和输出特性
指针作为函数参数时,可以实现输入和输出的双重功能。通过指针传递变量的地址,函数可以修改外部变量的值,实现输出;同时,指针本身也可以作为输入,传递初始值或状态。这种方式提高了函数的灵活性和效率。
|
1月前
|
C++
指针中的回调函数与qsort的深度理解与模拟
本文详细介绍了回调函数的概念及其在计算器简化中的应用,以及C++标准库函数qsort的原理和使用示例,包括冒泡排序的模拟实现。
17 1
|
1月前
利用指针函数
【10月更文挑战第2天】利用指针函数。
17 1
|
1月前
|
C++
析构造函数就是为了释放内存,就是在局部指针消失前释放内存,拷贝构造函数就是以构造函数为模块,在堆里面新开一块,同一个变量在堆里面的地址
本文讨论了C++中构造函数和析构函数的作用,特别是它们在管理动态内存分配和释放中的重要性,以及如何正确地实现拷贝构造函数以避免内存泄漏。
37 2
|
1月前
|
算法 搜索推荐 C语言
【C语言篇】深入理解指针4(模拟实现qsort函数)
【C语言篇】深入理解指针4(模拟实现qsort函数)
23 2
|
1月前
魔法指针 之 函数指针 回调函数
魔法指针 之 函数指针 回调函数
14 0
|
2月前
|
Linux
在Linux内核中根据函数指针输出函数名称
在Linux内核中根据函数指针输出函数名称
|
3月前
|
程序员 C语言
指针在函数参数和返回值中的使用
指针在函数参数和返回值中的使用
47 9