C++ 逻辑函数对象
什么是逻辑函数对象?
逻辑函数对象是C++ STL中的一组函数对象,专门用于执行逻辑运算操作。它们继承自 std::binary_function
或 std::unary_function
(在C++11之前),主要用于在STL算法中执行逻辑判断。
C++ STL提供了三种基本的逻辑函数对象:
std::logical_and
- 执行逻辑与操作std::logical_or
- 执行逻辑或操作std::logical_not
- 执行逻辑非操作
在现代C++(C++14及以上)中,std::unary_function
和 std::binary_function
已被弃用,逻辑函数对象不再继承自它们,但功能保持不变。
1. std::logical_and
std::logical_and
是一个二元函数对象,执行逻辑与操作,相当于C++中的 &&
运算符。
基本用法
#include <iostream>
#include <functional>
int main() {
std::logical_and<bool> logical_and_op;
bool result1 = logical_and_op(true, true); // true && true
bool result2 = logical_and_op(true, false); // true && false
bool result3 = logical_and_op(false, false); // false && false
std::cout << "true AND true = " << std::boolalpha << result1 << std::endl;
std::cout << "true AND false = " << result2 << std::endl;
std::cout << "false AND false = " << result3 << std::endl;
return 0;
}
输出结果:
true AND true = true
true AND false = false
false AND false = false
与STL算法结合使用
std::logical_and
可以与STL算法结合使用,特别是在需要组合多个条件的场景中:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 使用lambda和logical_and组合条件:大于3且小于8
auto inRange = [](int n) {
return std::logical_and<bool>()(n > 3, n < 8);
};
std::cout << "Numbers between 3 and 8: ";
std::copy_if(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, " "),
inRange);
std::cout << std::endl;
return 0;
}
输出结果:
Numbers between 3 and 8: 4 5 6 7
2. std::logical_or
std::logical_or
是一个二元函数对象,执行逻辑或操作,相当于C++中的 ||
运算符。
基本用法
#include <iostream>
#include <functional>
int main() {
std::logical_or<bool> logical_or_op;
bool result1 = logical_or_op(true, true); // true || true
bool result2 = logical_or_op(true, false); // true || false
bool result3 = logical_or_op(false, false); // false || false
std::cout << "true OR true = " << std::boolalpha << result1 << std::endl;
std::cout << "true OR false = " << result2 << std::endl;
std::cout << "false OR false = " << result3 << std::endl;
return 0;
}
输出结果:
true OR true = true
true OR false = true
false OR false = false
实际应用示例
以下是使用 std::logical_or
在过滤条件中的示例:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 使用logical_or找出小于3或大于7的数
auto outsideMiddle = [](int n) {
return std::logical_or<bool>()(n < 3, n > 7);
};
std::cout << "Numbers less than 3 or greater than 7: ";
std::copy_if(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, " "),
outsideMiddle);
std::cout << std::endl;
return 0;
}
输出结果:
Numbers less than 3 or greater than 7: 1 2 8 9 10
3. std::logical_not
std::logical_not
是一个一元函数对象,执行逻辑非操作,相当于C++中的 !
运算符。
基本用法
#include <iostream>
#include <functional>
int main() {
std::logical_not<bool> logical_not_op;
bool result1 = logical_not_op(true); // !true
bool result2 = logical_not_op(false); // !false
std::cout << "NOT true = " << std::boolalpha << result1 << std::endl;
std::cout << "NOT false = " << result2 << std::endl;
return 0;
}
输出结果:
NOT true = false
NOT false = true
与STL算法结合使用
std::logical_not
在反转条件时非常有用,特别是与其他函数对象或谓词结合使用:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
bool isEven(int n) {
return n % 2 == 0;
}
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 使用logical_not反转isEven条件,找出所有奇数
std::cout << "Odd numbers: ";
std::copy_if(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, " "),
std::not_fn(isEven)); // C++17中使用not_fn
std::cout << std::endl;
// 在C++17之前的替代方法
std::cout << "Odd numbers (alternative): ";
std::copy_if(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, " "),
[](int n) { return std::logical_not<bool>()(isEven(n)); });
std::cout << std::endl;
return 0;
}
输出结果:
Odd numbers: 1 3 5 7 9
Odd numbers (alternative): 1 3 5 7 9
组合使用逻辑函数对象
逻辑函数对象的真正威力在于它们可以被组合使用,创建复杂的条件判断:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
bool isEven(int n) {
return n % 2 == 0;
}
bool isGreaterThan5(int n) {
return n > 5;
}
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 找出偶数且大于5的数字
std::cout << "Even numbers greater than 5: ";
std::copy_if(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, " "),
[](int n) {
return std::logical_and<bool>()(isEven(n), isGreaterThan5(n));
});
std::cout << std::endl;
// 找出奇数或小于等于5的数字
std::cout << "Odd numbers or numbers <= 5: ";
std::copy_if(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, " "),
[](int n) {
return std::logical_or<bool>()(
std::logical_not<bool>()(isEven(n)),
std::logical_not<bool>()(isGreaterThan5(n))
);
});
std::cout << std::endl;
return 0;
}
输出结果:
Even numbers greater than 5: 6 8 10
Odd numbers or numbers <= 5: 1 2 3 4 5 7 9
实际应用场景
1. 数据过滤
逻辑函数对象特别适合用于数据过滤场景,例如在用户界面过滤显示项目:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <string>
struct Product {
std::string name;
double price;
bool inStock;
};
int main() {
std::vector<Product> products = {
{"Laptop", 999.99, true},
{"Phone", 499.99, false},
{"Tablet", 299.99, true},
{"Headphones", 99.99, true},
{"Camera", 399.99, false}
};
// 价格低于300且有货的产品
auto affordableAndAvailable = [](const Product& p) {
return std::logical_and<bool>()(p.price < 300.0, p.inStock);
};
std::cout << "Affordable and available products:" << std::endl;
for (const auto& product : products) {
if (affordableAndAvailable(product)) {
std::cout << "- " << product.name << " ($" << product.price << ")" << std::endl;
}
}
return 0;
}
输出结果:
Affordable and available products:
- Tablet ($299.99)
- Headphones ($99.99)
2. 条件组合
当需要基于多个条件进行复杂决策时,逻辑函数对象能够使代码更加清晰:
#include <iostream>
#include <vector>
#include <functional>
#include <string>
struct Student {
std::string name;
int mathScore;
int englishScore;
int scienceScore;
};
int main() {
std::vector<Student> students = {
{"Alice", 95, 88, 92},
{"Bob", 75, 82, 79},
{"Charlie", 88, 90, 85},
{"Diana", 70, 75, 68},
{"Eve", 92, 95, 94}
};
// 数学分数高于90且科学分数高于85,或者英语分数高于90的学生
auto isExcellent = [](const Student& s) {
return std::logical_or<bool>()(
std::logical_and<bool>()(s.mathScore > 90, s.scienceScore > 85),
s.englishScore > 90
);
};
std::cout << "Excellent students:" << std::endl;
for (const auto& student : students) {
if (isExcellent(student)) {
std::cout << "- " << student.name << std::endl;
}
}
return 0;
}
输出结果:
Excellent students:
- Alice
- Charlie
- Eve
自定义逻辑函数对象
除了使用STL提供的逻辑函数对象外,你还可以创建自己的自定义逻辑函数对象:
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义逻辑函数对象:检查数字是否在指定范围内
class InRange {
private:
int lower;
int upper;
public:
InRange(int low, int up) : lower(low), upper(up) {}
bool operator()(int value) const {
return value >= lower && value <= upper;
}
};
int main() {
std::vector<int> numbers = {1, 5, 10, 15, 20, 25, 30};
InRange inTens(10, 20);
std::cout << "Numbers between 10 and 20: ";
std::copy_if(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, " "),
inTens);
std::cout << std::endl;
return 0;
}
输出结果:
Numbers between 10 and 20: 10 15 20
总结
C++逻辑函数对象提供了一种灵活且可复用的方式来执行逻辑运算。它们在STL算法中特别有用,可以帮助我们:
- 使用
std::logical_and
执行逻辑与操作 - 使用
std::logical_or
执行逻辑或操作 - 使用
std::logical_not
执行逻辑非操作 - 组合多个逻辑判断来构建复杂条件
通过掌握这些函数对象,你可以编写更加清晰、更具表现力的代码,特别是在处理复杂条件判断和数据过滤时。
在C++17及更高版本中,可以使用 std::not_fn
作为 std::logical_not
的一种更方便的替代方法。同时,C++20引入了范围(ranges)库,为这些函数对象提供了更强大的应用场景。
练习
- 使用逻辑函数对象,编写代码找出一个整数向量中能被3整除但不能被5整除的所有数。
- 创建一个自定义的逻辑函数对象,用于检查一个字符串是否同时包含数字和大写字母。
- 使用
std::logical_and
和std::logical_or
实现XOR(异或)操作。
参考资源
- C++ 参考文档:std::logical_and
- C++ 参考文档:std::logical_or
- C++ 参考文档:std::logical_not