c++/c 函数指针用法

        既然说到了函数指针,我们先说说指针。指针其实就是存放对象的内存地址单元。在c语言中,指针的重要性是不言而喻的,不过指针引发的错误也很悲壮,用编程专家们的话说,再有经验的c程序员也可以在使用指针事出问题。虽然在c++中很多地方为了提高效率和避免出错用引用去代替指针,但是他们的区别还是很大的。

        1.引用在定义的时候必须初始化,而指针先定义时可以不初始化。2.引用不可以为空,而指针可以为空NULL。3.引用一当被初始化,后面就不可以再被修改指向别的对象,而指针可以任意修改。其实引用是通过指针来实现的,只是这些都是编译器完成的。

       

         函数说白了其实就是一系列指令的组合。编译器会为函数在内存中分配一块连续的存储区域,这块存储区域单元的首地址就是函数的入口地址,在编程时用函数名来标识。加入我们定义了一个变量用于存放函数首地址的指针,那么此指针变量就是指向函数的指针。

        

        函数指针的定义形式是这样的:函数返回值类型   (*指针变量名)(形参);这样在使用的时候很麻烦,每次用都需要这样写(*指针变量名)(实参),为了方便使用,我们使用typedef定义同义词,typedef 函数返回值类型 (*指针变量名) (形参),以后使用这种函数指针类型时,就可以直接使用指针变量名定义变量了。ps:那个括号是必须的,否则就变成了函数的返回值类型的指针了。它主要有三个用处:调用函数、作为函数的参数和转换表。

        首先看看typedef定义的简化好处:

#include <iostream>

using namespace std;

int test_return(int);
int test_return_add(int);


int main() {

	//不使用typedef
	int (*p_f_return)(int);					//声明函数指针变量p_f_return
	p_f_return = test_return;				//函数指针变量初始化为指向函数test_return的入口地址

	int (*p_f_return_add)(int);				//声明函数指针变量时又将函数声明重复了一遍
	p_f_return_add = test_return_add;
	

	//使用typedef时
	typedef int (*func_ptr)(int);			//定义函数指针的同义词func_ptr,以后直接使用同义词定义函数指针变量

	func_ptr p_f_return = test_return;
	func_ptr p_f_return_add = test_return_add;

	system("pause");

	return 0;
}

int test_return(int i) {
	return i;
}

int test_return_add(int i) {
	return i + 1;
}

        一看代码就明白了吧,使用typedef后定义函数指针变量简单的多了。

      看看使用函数指针如何调用函数

#include <iostream>

using namespace std;

int test_return(int);


int main() {

	//使用typedef时
	typedef int (*func_ptr)(int);			//定义函数指针的同义词func_ptr,以后直接使用同义词定义函数指针变量

	func_ptr p_f_return = test_return;

	//使用函数指针调用函数
	cout << p_f_return(1);

	system("pause");

	return 0;
}

int test_return(int i) {
	return i;
}
        呵呵,这样使用起来和函数一模一样了,很舒服吧。

        继续看看函数指针作为参数的情况,此时调用函数时需要传递一个函数指针实参,回调函数就是这种原理。

#include <iostream>

using namespace std;

int test_return(int (*)(int), int);
int test_param(int);


int main() {

	typedef int (*func_ptr)(int);			//定义函数指针的同义词func_ptr,以后直接使用同义词定义函数指针变量

	func_ptr p_f_param = test_param;

	//调用函数时,传递函数地址
	cout << test_return(p_f_param, 2);

	system("pause");

	return 0;
}

//函数指针作为形参
int test_return(int (*p_f_param)(int), int i) {
	return (*p_f_param)(i);
}

int test_param(int i) {
	return i;
}
        最后看看转换表的情形,比如一个计算器的程序,传入两个操作数和一个操作符,类似于下面的代码
switch (oper)
{
case ADD:
	result = add(op1, op2);
	break;

case SUB:
	result = sub(op1, op2);
	break;

case MUL:
	result = mul(op1, op2);
	break;

case DIV:
	result = div(op1, op2);
	break;
}
这样有很大的不好,假设操作符很多,岂不是要写很长。这时候将所有的操作放到一个函数指针数组中去,这样直接选择正确的函数指针就能执行相应的函数了。如下代码
#include <iostream>

using namespace std;

double add(double, double);
double sub(double, double);
double mul(double, double);
double div(double, double);

//函数指针数组,保存所有的操作函数
double (*oper_func[])(double, double) = {add, sub, mul, div};

int main() {

	//测试add方法
	double result = oper_func[0](1.0, 2.0);
	cout << result;

	system("pause");

	return 0;
}

double add(double d1, double d2) {
	return d1 + d2;
}

double sub(double d1, double d2) {
	return d1 - d2;
}

double mul(double d1, double d2) {
	return d1 * d2;
}

double div(double d1, double d2) {
	return d1 / d2;
}
           转换表的那块来自《c和指针》。函数指针用的最多的就是回调函数了,Windows系统的消息机制大量使用了回调。函数指针的用途较广,还是需要好好理解下。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值