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

本文深入浅出地介绍了函数指针的概念、定义及使用方法。通过示例代码详细讲解了函数指针的赋值、作为参数及返回指向函数的指针等应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数指针,指向函数的指针,顾名思义,其本质还是一个指针!可以对其进行赋值(包括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。

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

<think>好的,我现在需要解决用户关于在C++中使用TCHAR指针赋值文件路径字符串的问题。首先,我得回忆一下TCHAR的用途和相关知识。TCHAR在Windows编程中用于处理多字节字符集(MBCS)和Unicode(UTF-16)的兼容性。根据是否定义了_UNICODE宏,TCHAR会被定义为char或wchar_t。因此,使用TCHAR时需要考虑字符编码的问题。 用户提到的是指针赋值,可能涉及字符串的初始化和赋值操作是否正确。常见的问题可能包括类型不匹配、字符串字面量的编码问题,以及内存管理是否正确。例如,直接赋值字符串字面量给TCHAR指针可能需要使用_T()或TEXT()宏来确保字符串的正确类型。 接下来,我需要检查示例代码中可能出现的错误。例如,如果用户写了类似TCHAR* path = "C:\\path";,这在Unicode构建下会出错,因为"..."是char*类型,而TCHAR可能是wchar_t。正确的做法应该是使用TEXT宏包裹字符串,如TCHAR* path = TEXT("C:\\path");。 另一个问题是内存分配。直接赋值字符串字面量给指针是可行的,但如果需要修改字符串内容,应该分配足够的缓冲区,比如使用数组或动态内存分配。此外,处理文件路径时,使用Windows API的PathCchCombine或类似的函数可以安全地拼接路径,避免缓冲区溢出。 还需要考虑跨平台和不同字符集编译的情况。比如,使用TCHAR相关的函数(如_tcscpy_s代替strcpy或wcscpy),以及正确处理字符串长度和内存分配大小(使用_countof宏获取数组元素个数)。 可能用户遇到的问题包括编译错误(类型不匹配)、运行时错误(访问违规)或者路径处理不正确。需要逐一分析这些情况,并提供正确的代码示例和解释。 最后,总结注意事项,比如始终使用TEXT宏、优先使用安全字符串函数、区分字符集配置等,确保用户能够正确使用TCHAR指针处理文件路径。</think>在C++中使用TCHAR指针处理文件路径字符串时,需要注意Windows字符编码的兼容性问题。以下是关键要点和示例: 1. **基本赋值规范** - 必须使用`TEXT()`宏包裹字符串字面量 - 推荐使用安全字符串函数 ```cpp TCHAR* path = TEXT("C:\\Program Files\\App"); // 正确赋值 TCHAR buffer[MAX_PATH]; _tcscpy_s(buffer, _countof(buffer), path); // 安全拷贝 ``` 2. **动态内存分配** ```cpp const TCHAR* basePath = TEXT("D:\\Documents"); TCHAR* fullPath = new TCHAR[MAX_PATH]; _stprintf_s(fullPath, MAX_PATH, TEXT("%s\\data.txt"), basePath); // 使用后需释放内存 delete[] fullPath; ``` 3. **路径拼接最佳实践** 使用Windows API实现安全拼接: ```cpp #include <PathCch.h> TCHAR path1[MAX_PATH] = TEXT("C:\\Windows"); TCHAR path2[MAX_PATH]; PathCchCombine(path2, MAX_PATH, path1, TEXT("System32")); ``` 4. **常见问题解决方案** | 问题现象 | 错误原因 | 修正方法 | |---------|---------|---------| | 编译错误C2440 | 未使用TEXT宏包裹ANSI字符串 | 添加TEXT()或_T()宏 | | 访问冲突异常 | 未分配内存直接修改指针 | 改用数组或动态分配 | | 路径显示乱码 | 字符集配置与编码不匹配 | 统一使用UNICODE字符集 | 5. **字符集配置注意事项** - 在项目属性中设置: - 使用Unicode字符集:`_UNICODE`和`UNICODE`已定义 - 使用多字节字符集:上述宏未定义 - 通过预处理指令处理兼容: ```cpp #ifdef _UNICODE #define tcout wcout #else #define tcout cout #endif ``` 6. **跨API兼容方案** 推荐使用通用版本函数: ```cpp //
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值