跳到主要内容

C++ 逻辑函数对象

什么是逻辑函数对象?

逻辑函数对象是C++ STL中的一组函数对象,专门用于执行逻辑运算操作。它们继承自 std::binary_functionstd::unary_function(在C++11之前),主要用于在STL算法中执行逻辑判断。

C++ STL提供了三种基本的逻辑函数对象:

  • std::logical_and - 执行逻辑与操作
  • std::logical_or - 执行逻辑或操作
  • std::logical_not - 执行逻辑非操作
备注

在现代C++(C++14及以上)中,std::unary_functionstd::binary_function 已被弃用,逻辑函数对象不再继承自它们,但功能保持不变。

1. std::logical_and

std::logical_and 是一个二元函数对象,执行逻辑与操作,相当于C++中的 && 运算符。

基本用法

cpp
#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算法结合使用,特别是在需要组合多个条件的场景中:

cpp
#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++中的 || 运算符。

基本用法

cpp
#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 在过滤条件中的示例:

cpp
#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++中的 ! 运算符。

基本用法

cpp
#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 在反转条件时非常有用,特别是与其他函数对象或谓词结合使用:

cpp
#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

组合使用逻辑函数对象

逻辑函数对象的真正威力在于它们可以被组合使用,创建复杂的条件判断:

cpp
#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. 数据过滤

逻辑函数对象特别适合用于数据过滤场景,例如在用户界面过滤显示项目:

cpp
#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. 条件组合

当需要基于多个条件进行复杂决策时,逻辑函数对象能够使代码更加清晰:

cpp
#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提供的逻辑函数对象外,你还可以创建自己的自定义逻辑函数对象:

cpp
#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)库,为这些函数对象提供了更强大的应用场景。

练习

  1. 使用逻辑函数对象,编写代码找出一个整数向量中能被3整除但不能被5整除的所有数。
  2. 创建一个自定义的逻辑函数对象,用于检查一个字符串是否同时包含数字和大写字母。
  3. 使用 std::logical_andstd::logical_or 实现XOR(异或)操作。

参考资源