C++函数过程 函数→函数指针→函数模板→仿函数|函数对象→lambda表达式

C++函数的进化

(函数→函数指针→函数模板→仿函数/函数对象→lambda表达式)

知识点梳理-举例说明(统计数组元素个数:【类似std::count_if()函数】,比较符合条件的数量信息)

过程1(函数)

最简单的方式

int countMatchElements(int* beg, int* end)
{
	int result = 0;
	for (; beg != end; ++beg)
	{
		if (*beg > 20) ++result;
	}
	return result;
}
int main()
{
	int intArray[] = { 11, 16 ,21,19,17,30 };
	//统计大于20的元素的数量
    //intArray, intArray + 6 两个实参传入起始位置到countMatchElements(int* beg, int* end)形参中
	std::cout << countMatchElements(intArray, intArray + 6) << std::endl;
    return 0;
}

过程2(函数指针)

如果还要统计小于10、大于25的元素数量,可以将countMatchElements函数中判断的变化点封装并独立出来

//函数指针:让“函数”变成“变量”,将“行为”“数据化”
int countMatchElements(int* beg, int* end, bool(*pred)(const int&))
{
	int result = 0;
	for (; beg != end; ++beg)
	{
		if (pred(*beg)) ++result;
	}
	return result;
}
bool isGreater20(const int& val) { return val > 20; }
bool isGreater25(const int& val) { return val > 25; }
bool isLess10(const int& val) { return val < 10; }

int main()
{
	int intArray[] = { 11, 16 ,21,19,17,30 };
	//过程2:函数指针
    //统计大于20的元素的数量
    std::cout << countMatchElements(intArray, intArray + 6, isGreater20) << std::endl;
    //统计大于25的元素数量
    std::cout << countMatchElements(intArray, intArray + 6, isGreater25) << std::endl;
    //统计小于10的元素数量
    std::cout << countMatchElements(intArray, intArray + 6, isLess10) << std::endl;
    return 0;
}

过程3(函数模板)

提高函数通用性。目前只能处理int类型,使用template可以使用其他种数据类型

//函数模板:独立于类型的函数,可以产生函数特定类型的版本
template<typename T>
int countMatchElements(T* beg, T* end, bool(*pred)(const T&))
{
	int result = 0;
	for (; beg != end; ++beg)
	{
		if (pred(*beg)) ++result;
	}
	return result;
}
bool isGreater20(const int& val) { return val > 20; }		//阈值写死的,如果用户想自己定义,可以使用仿函数实现
bool isTinyStr(const std::string& val) { return val.size() <= 3; }

int main()
{
	int intArray[] = { 11, 16 ,21,19,17,30 };
	//过程3:函数模板
	//统计大于20的元素的数量
	std::cout << countMatchElements(intArray, intArray + 6, isGreater20) << std::endl;
	//统计字符串长度小于3的数量
	std::string strArray[] = { "the","template", "is","a","useful", "tool" };
	std::cout << countMatchElements(strArray, strArray + 6, isTinyStr) << std::endl;
    return 0;
}

过程4(仿函数)

例如在设置统计数量的阈值的时候,用户自己定义阈值

//仿函数:定义调用操作符,行为类似于函数的对象
//仿函数的问题:仿函数不能给函数指针赋值,解决办法是将函数指针也转为模板
template<typename T, typename Pred>
int countMatchElements(T* beg, T* end, Pred pred)
{
	int result = 0;
	for (; beg != end; ++beg)
	{
		if (pred(*beg)) ++result;
	}
	return result;
}
//声明仿函数对应的类
template<typename T>
struct Greater
{
	T mVal;	//持有的状态
	explicit Greater(T value) : mVal(value) {}	//构造函数初始化状态mVal
	bool operator()(const T& val) const { return val > mVal; }	//重载该函数调用操作符,还拥有自己的数据成员
};
int main()
{
	int intArray[] = { 11, 16 ,21,19,17,30 };
    /*过程4:仿函数
    创建函数对象,也就是仿函数,这个对象可以伪装成普通函数,使用小括号调用*/
    Greater<int> greater20{ 20 };	//将阈值设置为20	
    /*这里出现一个问题:仿函数遇到函数指针,会发生无法给函数指针赋值的问题,error:
    错误	C2784	“int countMatchElements(T*, T*, bool(__cdecl*)(const T&))”: 未能从“Greater<int>”为“bool(__cdecl*)(const T&)”推导 模板 参数;
    错误	C2672	“countMatchElements” : 未找到匹配的重载函数
    STL标准库的解决办法是: 将函数模板进行到底,用模板参数表示可调用类型,适应能力更强*/
	std::cout << countMatchElements(intArray, intArray + 6, greater20) << std::endl;
    return 0;
}

过程5(lambda表达式)

//提高代码简洁度 使用lambda重构,提高可读性,不需要声明仿函数对应的类
template<typename T, typename Pred>
int countMatchElements(T* beg, T* end, Pred pred)
{
	int result = 0;
	for (; beg != end; ++beg)
	{
		if (pred(*beg)) ++result;
	}
	return result;
}

int main()
{
	int intArray[] = { 11, 16 ,21,19,17,30 };
	//过程5:提高代码简洁度,使用lambda表达式
	auto greater20 = [](auto& val) ->bool {return val > 20; };
	std::cout << countMatchElements(intArray, intArray + 6, greater20) << std::endl;
    return 0;
}
posted @   菜鸟C_5022  阅读(72)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
点击右上角即可分享
微信分享提示