Joe1sn's Cabinet

【免杀】C++函数进化

C++的函数进化小结

函数

有这样一个问题

1
2
3
4
5
6
7
#include <iostream>

int main(){
int IntArray = { 12, 13, 35, 16, 6, 5, 5, 12, 4, 13, 38, 35, 37, 33, 35, 15, 36, 14, 13, 12 };
//统计大于20的数字
return 0;
}

那么很自然的给出解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

int CountMatch(int* start, int* end){
int sum = 0;
for (; start < end ; start++)
{
if (*start > 20)
sum++;
}
return sum;
}

int main(){
int IntArray[] = { 12, 13, 35, 16, 6, 5, 5, 12, 4, 13, 38, 35, 37, 33, 35, 15, 36, 14, 13, 12 };
//统计大于20的数字
std::cout<<"Matches: "<<CountMatch(IntArray,IntArray+20)<<std::endl;
return 0;
}

函数指针

这个时候的需要满足 统计大于10的数字 或者 统计小于35的数字,那么可以将*start > 20这一段包装一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

int CountMatch(int* start, int* end, bool(*ConditionFunc)(const int &)){
int sum = 0;
for (; start < end ; start++)
{
if (ConditionFunc(*start))
sum++;
}
return sum;
}

bool bGreat20(const int &num){ return num > 20; }
bool bGreat10(const int &num){ return num > 10; }
bool bLess35(const int &num){ return num < 35; }

int main(){
int IntArray[] = { 12, 13, 35, 16, 6, 5, 5, 12, 4, 13, 38, 35, 37, 33, 35, 15, 36, 14, 13, 12 };
//统计大于20的数字
std::cout<<"Greater than 20 Matches: "<<CountMatch( IntArray, IntArray+20, bGreat20 )<<std::endl;
std::cout<<"Greater than 10 Matches: "<<CountMatch( IntArray, IntArray+20, bGreat10 )<<std::endl;
std::cout<<"Greater than 20 Matches: "<<CountMatch( IntArray, IntArray+20, bLess35 )<<std::endl;
return 0;
}

图片上的代码有点小问题

image-20230626083232291

在c语言中可以这样写,虽然编译会有警告,但是仍然可以生成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

int CountMatch(int* start, int* end, void *function_pointer(int)){
int sum = 0;
for (; start < end ; start++)
{
if (function_pointer(*start))
sum++;
}
return sum;
}

int Pointer(int start){
printf("Happy\n");
return 1;
}

int main(){
int IntArray[] = { 12, 13, 35, 16, 6, 5, 5, 12, 4, 13, 38, 35, 37, 33, 35, 15, 36, 14, 13, 12 };
//统计大于20的数字
printf("Matches: %d\n",CountMatch(IntArray,IntArray+20, Pointer));
return 0;
}

在c中伴随着指针的引用*p和解引用&p,C对指针的类型安全性进行了更严格的限制。C++中的指针类型必须与所指向的对象类型匹配,不允许进行隐式类型转换。这可以帮助减少潜在的类型错误和编程错误。

函数模板

上面的函数只能支持int,使用函数模板能让他支持更多类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

template <typename T>
int CountMatch(T* start, T* end, bool(*ConditionFunc)(const T &)){
int sum = 0;
for (; start < end ; start++)
{
if (ConditionFunc(*start))
sum++;
}
return sum;
}

bool bGreat20(const int &num){ return num > 20; }
bool bGreat10(const int &num){ return num > 10; }
bool bLess35(const int &num){ return num < 35; }
bool bTiny(const std::string &val){ return val.size() <= 3; }

int main(){
int IntArray[] = { 12, 13, 35, 16, 6, 5, 5, 12, 4, 13, 38, 35, 37, 33, 35, 15, 36, 14, 13, 12 };
std::string StrArray[] = {"Hello","world","This","is","a","test"};
//统计大于20的数字
std::cout<<"Greater than 20 Matches: "<<CountMatch( IntArray, IntArray+20, bGreat20 )<<std::endl;
std::cout<<"Greater than 10 Matches: "<<CountMatch( IntArray, IntArray+20, bGreat10 )<<std::endl;
std::cout<<"Greater than 20 Matches: "<<CountMatch( StrArray, StrArray+6, bTiny )<<std::endl;
return 0;
}

仿函数

在条件中如果需要处理用户传入的数字怎么办

仿函数(Functor)是C++中的一个概念,指的是可以像函数一样使用的对象。它实际上是一个类或结构体,重载了函数调用运算符 operator(),使得对象可以像函数一样进行调用操作。

chatGPT给了我这样一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

// 定义一个仿函数类
class AddFunctor {
public:
int operator()(int a, int b) {
return a + b;
}
};

int main() {
// 创建一个仿函数对象
AddFunctor add;

// 使用仿函数对象进行调用
int result = add(3, 4);

// 输出结果
std::cout << "Result: " << result << std::endl;

return 0;
}

在这里可以这样写

1
2
3
4
5
6
7
8
template <typename T>
struct Greater
{
T mVal; //持有的状态
explicit Greater(T value):
mVal(value){}
bool operator()(const T &val) const { return val>mVal; }
};
  • explicit:通过在单参数构造函数前添加 explicit 关键字,可以防止编译器在需要进行类型转换的情况下自动调用该构造函数。
  • operator:仿函数的实现,使得对象可以像函数一样进行调用操作。

抓函数中生成一个对象(该标准仅在c++11及以上支持),但是这样函数指针就没法用了

1
Greater<int> greater20{20};

可以学习标准库中的操作将模板持续下去

1
2
3
4
5
6
7
8
9
10
template <typename T, typename fCompare>
int CountMatch(T* start, T* end, fCompare ConditionFunc){
int sum = 0;
for (; start < end ; start++)
{
if (ConditionFunc(*start))
sum++;
}
return sum;
}

最后程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>

template <typename T, typename fCompare>
int CountMatch(T* start, T* end, fCompare ConditionFunc){
int sum = 0;
for (; start < end ; start++)
{
if (ConditionFunc(*start))
sum++;
}
return sum;
}

template <typename T>
struct Greater
{
T mVal; //持有的状态
explicit Greater(T value):
mVal(value){}
bool operator()(const T &val) const { return val>mVal; }
};



int main(){
int IntArray[] = { 12, 13, 35, 16, 6, 5, 5, 12, 4, 13, 38, 35, 37, 33, 35, 15, 36, 14, 13, 12 };
std::string StrArray[] = {"Hello","world","This","is","a","test"};
Greater<int> greater20{20};
//统计大于20的数字
std::cout<<"Greater than 20 Matches: "<<CountMatch( IntArray, IntArray+20, greater20 )<<std::endl;
return 0;
}

lambda表达式

这个我再Qt上用的挺多的,他是匿名函数的实现

1
2
3
4
5
6
7
int main(){
int IntArray[] = { 12, 13, 35, 16, 6, 5, 5, 12, 4, 13, 38, 35, 37, 33, 35, 15, 36, 14, 13, 12 };
auto greater20 = [](auto &val) -> bool { return val > 20; };
//统计大于20的数字
std::cout<<"Greater than 20 Matches: "<<CountMatch( IntArray, IntArray+20, greater20 )<<std::endl;
return 0;
}