C++ 仿函数
1. 仿函数的基本用法
仿函数是一个类或结构体对象,它通过重载函数调用运算符 operator()
,使得该对象可以像普通函数一样被调用。
示例1:实现一个加法器
class Adder {
public:
Adder(int num) : num_(num) {} // 构造函数保存状态(加数)
// 重载 operator(),执行加法
int operator()(int x) const {
return x + num_;
}
private:
int num_;
};
int main() {
Adder add5(5); // 创建一个加5的仿函数
std::cout << add5(10); // 输出 15(等价于 add5.operator()(10))
return 0;
}
说明:
Adder
类的对象add5
保存了状态num_ = 5
。- 调用
add5(10)
时,实际上是调用operator()(10)
,实现了10 + 5
。
2. 仿函数与STL算法
示例2:用仿函数自定义排序规则
// 仿函数:按字符串长度排序
class CompareLength {
public:
bool operator()(const std::string& a, const std::string& b) const {
return a.size() < b.size();
}
};
int main() {
std::vector<std::string> words = {"apple", "banana", "cherry", "date"};
// 使用仿函数作为排序规则
std::sort(words.begin(), words.end(), CompareLength());
// 输出排序结果:date apple banana cherry
for (const auto& word : words) {
std::cout << word << " ";
}
return 0;
}
说明:
CompareLength
的operator()
接受两个字符串,比较它们的长度。std::sort
通过仿函数对象实现自定义排序。
3. 仿函数保存复杂状态
示例3:统计函数调用次数
class Counter {
public:
Counter() : count_(0) {}
void operator()(int x) {
std::cout << x << " ";
count_++;
}
int getCount() const { return count_; }
private:
int count_;
};
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5};
Counter counter;
// 遍历容器并统计元素个数
std::for_each(nums.begin(), nums.end(), counter);
std::cout << "\nCount: " << counter.getCount(); // 输出 Count: 5
return 0;
}
说明:
Counter
的仿函数在每次调用时递增计数器,实现状态保存。
4. 仿函数与模板结合
示例4:泛型乘法器
template <typename T>
class Multiplier {
public:
Multiplier(T factor) : factor_(factor) {}
T operator()(T x) const {
return x * factor_;
}
private:
T factor_;
};
int main() {
Multiplier<int> times3(3);
std::cout << times3(4); // 输出 12
Multiplier<double> times2_5(2.5);
std::cout << times2_5(4.0); // 输出 10.0
return 0;
}
说明:
- 模板仿函数可以处理任意类型(如
int
或double
)。
总结
- 仿函数的优势:
- 可保存状态(通过成员变量)。
- 支持模板和复杂逻辑。
- 与STL算法无缝配合(如
std::sort
,std::transform
)。
- 适用场景:
- 需要复用或模板化的函数逻辑。
- 需要保存多次调用之间的状态。
- 替代C风格函数指针,提升安全性和性能。