【C++】仿函数
孤寂大仙v 2024-10-04 16:35:11 阅读 63
🔥个人主页🔥:孤寂大仙V
🌈收录专栏🌈:C++从小白到高手
🌹往期回顾🌹:【C++】STL----deque
🔖 流水不争,争的是滔滔不息。
文章目录
一、仿函数的介绍仿函数的优点
二、仿函数的使用使用仿函数进行排序仿函数具有灵活性仿函数在实际中的简单使用
一、仿函数的介绍
仿函数(Functors)是一个在编程中常用的术语,特别是在面向对象编程和函数式编程中。它主要用于描述一个对象,这个对象表现得像函数一样,可以像调用函数一样使用。简单来说,仿函数是可以被调用的对象。
在面向对象编程中,仿函数是通过重载函数调用运算符 operator() 实现的。一个仿函数对象的行为就像一个函数,尽管它本质上是一个类的实例。例如,在C++中,我们可以通过重载 operator() 来实现仿函数。
<code>class Add
{ -- -->
public:
Add(int x)
:_val(x)
{ }
int operator()(int y) //重载()操作符,使对象可以像函数一样调用。
{
return _val + y;
}
private:
int _val;
};
int main()
{
Add add(5); // 创建一个仿函数对象
cout << add(10) << endl; // 输出 15,因为 5 + 10 = 15
return 0;
}
Add 类是一个仿函数类,通过重载 operator(),我们可以像使用普通函数那样调用 Add 的实例。
仿函数的优点
状态保存:函数对象(仿函数)可以保存状态,比如在上面的例子中,Adder 类保存了一个初始值 val。灵活性:由于仿函数是一个类对象,可以利用类的成员函数、构造函数等实现更复杂的功能。泛型编程的便利性:在像 C++ 标准库的模板算法中,仿函数常常被用来作为参数传递给算法函数,这比简单的函数指针要灵活得多。
二、仿函数的使用
使用仿函数进行排序
仿函数常用于STL中的排序操作,例如std::sort()函数。
class Greater
{
public:
bool operator()(int a, int b)
{
return a > b; // 排降序
}
};
int main() {
std::vector<int> v = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 10 };
Greater cmp;
std::sort(v.begin(), v.end(), cmp);
for (int num : v) {
std::cout << num << " ";
}
return 0;
}
仿函数具有灵活性
仿函数 可以具有任意数量的参数,并可以用于各种不同的操作。这使得它们非常灵活,可以根据需要进行定制。
<code>class ADD
{ -- -->
public:
int operator()(int a, int b)
{
return a + b;
}
};
class SUB
{
public:
int operator()(int a, int b)
{
return a - b;
}
};
int main() {
ADD add;
SUB sub;
int a = add(5, 3);
int b = sub(5, 3);
cout << a << endl;
cout << b << endl;
return 0;
}
仿函数在实际中的简单使用
在写一些代码的时候,可能会使用比较大小的操作符进行排序。比如建堆,我们写了一个建大堆的接口,如果我们想要建小堆又要写一个和建大堆类似大的代码,这时候就会很麻烦。但是我们用仿函数就可以有效规避这一问题。
<code>#include<vector>
template<class T>
class Less
{ -- -->
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
template<class T>
class Greater
{
public:
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
namespace bit
{
// 默认是大堆
template<class T, class Container = vector<T>, class Compare = Less<T>>
class priority_queue
{
public:
void AdjustUp(int child)
{
Compare com;
int parent = (child - 1) / 2;
while (child > 0)
{
//if (_con[parent] < _con[child])
if(com(_con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
void AdjustDown(int parent)
{
// 先假设左孩子小
size_t child = parent * 2 + 1;
Compare com;
while (child < _con.size()) // child >= n说明孩子不存在,调整到叶子了
{
// 找出小的那个孩子
//if (child + 1 < _con.size() && _con[child] < _con[child + 1])
if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
{
++child;
}
//if (_con[parent] < _con[child])
if (com(_con[parent],_con[child]))
{
swap(_con[child], _con[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDown(0);
}
const T& top()
{
return _con[0];
}
size_t size() const
{
return _con.size();
}
bool empty() const
{
return _con.empty();
}
private:
Container _con;
};
}
当然这只是一个简单的应用。
上一篇: VsCode调试时报错:preLaunchTask”C/C++: gcc.exe 生成活动文件”已终止,退出代码为 -1。
下一篇: 【C++】queue和priority_queue
本文标签
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。