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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报