C++基础(十三)函数指针

函数指针,指向函数的指针,顾名思义,其本质还是一个指针!可以对其进行赋值(包括nullptr),当然也能判断是否为空。

函数的类型,由它的返回类型和形参类型、形参个数共同决定,与函数名无关。所以函数指针,也只关心这些。

1、定义

定义一个函数指针,只需要指定返回值类型形参(包括个数和类型)。在返回值和形参类型中间,加上函数指针的变量名,以及"*",并用一对小括号包起来即可。如下:

返回类型 (*函数指针名)(形参)

例如:double(*pf)(double)。

注意两点:

(1)"*pf"外的括号必须加上。如果不加上,则是 double*pf(double),含义完全变了:pf是一个返回double* 类型的形参为double类型的函数;

(2)如果函数指针对应的函数没有返回值,在声明函数指针时,void也不能少。例如:void(*pf)()。

2、使用

(1)赋值

当我们把函数名当做一个值使用时,该函数自动地转换成指针。

函数指针的赋值,可以有一下两种形式:

#include <iostream>

void PrintInfo(){}

int _tmain(int argc, _TCHAR* argv[])
{
	void(*pf)() = nullptr;
	pf = PrintInfo;
	pf = &PrintInfo;

	system("pause");
	return 0;
}

可以在函数名前面加上取地址符"&",也可以不加。

(2)作为函数的参数

函数指针最常用的的情景之一就是作为函数的参数使用,其用法和指针完全一致。

代码如下:


#include <iostream>

double GetPrice_Discount(double dOriginal)
{
	return dOriginal * 0.85;
}

double GetPrice_Reduction(double dOriginal)
{
	if (dOriginal >= 300)
		return dOriginal - 40;
	return dOriginal;
}

void PrintPrince(double(*pf)(double), double dOriginal)
{
	if (!pf)
		std::cout << "错误!函数指针为空!" << std::endl;
	else
		std::cout << "折扣后价格:" << pf(dOriginal) << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	double dOriginal = 325;	
	std::cout << "原价:" << dOriginal << std::endl;
	
	double(*pf)(double) = nullptr;

	PrintPrince(pf, dOriginal);

	pf = GetPrice_Discount;
	std::cout << "打8.5折,";
	PrintPrince(pf, dOriginal);

	pf = GetPrice_Reduction;
	std::cout << "满300减40,";
	PrintPrince(pf, dOriginal);


	system("pause");
	return 0;
}

执行结果如下:

 

代码逻辑很简单,首先定义了两个函数,接收一个double类型的原价,实现不同的打折方式,返回打折后的实际价格。这两个函数的参数和返回值类型都一致,适用于同一类型的函数指针。

接着定义了一个PrintPrince函数,接受两个参数:函数指针-打折函数;double类型的值-原价。

值得注意的是,这个函数内部对pf是否为nullptr进行了判断,如果是,则给出提示信息;不是,则调用函数获取打折后的价格并打印出来。

主函数里先定义了一个价格并输出,接着定义了一个函数指针并赋值为nullptr,调用PrintPrince,此时pf为空,则会打印出错误的提示信息。后面两个相似的赋值和函数调用,打印出不同优惠方式下不同的实际价格。

(3)返回指向函数的指针

和数组类似,函数的返回值不能是一个函数,但是可以是一个指向函数的指针。

例如上面的打折问题,很多时候打折方案是灵活变动的,客户端根本不需要知道所有的优惠策略,只需要获取到最优的方案即可。类似这样的多种算法,有一种叫做策略模式的设计模式非常契合。但如果算法简单且数量不多的话,用策略模式就显得大材小用。假如有个函数可以筛选并返回最优的策略(指向函数的指针)就能满足要求,再直接使用这个指向函数的指针就能得到最优策略折扣后的实际价格。

函数的返回值,是一种类型(内置类型或者自定义的类型),但是函数指针本质上是一个指针变量,并不是一种类型,显然返回值无法直接用上面的那些pf。如何定义一个指向函数的指针类型呢?

很容易想到类型别名,这里用类型别名就会显得非常简单,如下:

using PF = double(*)(double);

注意,这里的"(*)"必不可少,表示这是一个指向函数的指针。如果没有,则表示一种函数类型,并非指针。

完整的代码如下:

#include <iostream>

double GetPrice_Discount(double dOriginal)
{
	return dOriginal * 0.85;
}

double GetPrice_Reduction(double dOriginal)
{
	if (dOriginal >= 300)
		return dOriginal - 40;
	return dOriginal;
}

using PF = double(*)(double);
PF GetBest(double dOriginal)
{
	double dPrice_Discount = GetPrice_Discount(dOriginal);
	double dPrice_Reduction = GetPrice_Reduction(dOriginal);
	if (dPrice_Discount < dPrice_Reduction)
		return GetPrice_Discount;
	else
		return GetPrice_Reduction;
}

int _tmain(int argc, _TCHAR* argv[])
{
	double dOriginal = 325;
	std::cout << "原价:" << dOriginal << std::endl;

	PF pf_best = GetBest(dOriginal);
	std::cout << "最优折扣后的价格:" << pf_best(dOriginal) << std::endl;

	system("pause");
	return 0;
}

执行结果如下:

需要注意一点的是,这里的PF是一种类型,所以需要定义一个变量pf_best。

除了以上的声明方式外,还有其他的方式,但形式非常复杂,对代码阅读和后期的维护非常不友好,此处不展开。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值