C++中如何通过模板传递布尔过滤函数实现数据过滤?
C++中通过模板传递过滤函数实现数据过滤
我尝试用布尔函数过滤数据,写了一段有错误的代码,想知道C++里能不能像Lua那样通过模板传递过滤函数参数来实现这个功能,以下是我的错误代码:
#include <iostream> #include <cstring> #include <vector> using namespace std; class Person { private: string name; int age; double height; char gender; public: Person(string name,int age,double height,char gender); string getName() {return name}; int getAge() { return age; } double getHeight() { return height; } char getGender() { return gender; } } Person::Person(string name,int age, double height,char gender) { this->name = name; this->age = age; this->height = height; this->gender = gender; } bool IsName(Person p, string name) { if(p.getName == name) return true; return false; } int IsAge(Person p, int age) { if(p.getAge == age) return true; return false; } double IsHeight(Person p, double height) { if(p.getHeight == height) return true; return false; } bool IsGender(Person p, char gender) { if(p.getGender == gender) return true; return false; } class Group { public: vector <Person> People; int getPersonCount(bool (*filter)(int)); } template <class T> int Group::getPersonCount(bool (*filter)(T), T t) { int ct = 0; for(int i=0;i<People.size();i++) if(People[i],filter(t)) ct++; return ct; } int main() { Person p1("Alice",24,1.80,'F'), p2("Bob",18,1.60,'M'), p3("Charlie",30,1.70,'M'); Group g; g.People.push_back(p1); g.People.push_back(p2); g.People.push_back(p3); cout<<g.getPersonCount(&IsName,"Alice"); return 0; }
代码中的错误点
- Person类语法错误:
getName()函数末尾缺少分号,应改为string getName() {return name;};- Person类定义结束后必须加
;,这是C++类定义的语法要求
- 成员函数调用错误:所有过滤函数中调用Person的getter方法时未加括号,比如
p.getName == name应改为p.getName() == name - 返回值类型错误:
IsAge和IsHeight的返回值类型应为bool,而非int和double - 参数效率问题:过滤函数的Person参数应使用
const引用,避免不必要的对象拷贝 - 函数声明与实现不匹配:
- Group类中声明的
getPersonCount参数为bool (*filter)(int),与模板实现的参数完全不兼容 - 模板函数的循环判断逻辑错误:
if(People[i],filter(t))应改为if(filter(People[i], t)),过滤函数需要同时接收Person对象和目标值
- Group类中声明的
- 函数指针类型不匹配:
IsName的签名是bool(Person, string),但模板期望的是bool(T),类型无法适配
修正后的实现代码
要实现通过模板传递过滤函数的功能,需要让模板适配过滤函数的签名,以下是修正后的完整代码:
#include <iostream> #include <vector> #include <string> using namespace std; class Person { private: string name; int age; double height; char gender; public: // 使用初始化列表简化构造函数 Person(string name, int age, double height, char gender) : name(std::move(name)), age(age), height(height), gender(gender) {} // 标记getter为const成员函数,保证能被const引用调用 string getName() const { return name; } int getAge() const { return age; } double getHeight() const { return height; } char getGender() const { return gender; } }; // 过滤函数:用const引用避免拷贝,提升效率 bool IsName(const Person& p, const string& name) { return p.getName() == name; } bool IsAge(const Person& p, int age) { return p.getAge() == age; } bool IsHeight(const Person& p, double height) { return p.getHeight() == height; } bool IsGender(const Person& p, char gender) { return p.getGender() == gender; } class Group { public: vector<Person> People; // 模板函数:适配不同类型的过滤目标值 template <typename T> int getPersonCount(bool (*filter)(const Person&, const T&), const T& target) { int count = 0; // 用范围for循环简化遍历 for (const auto& person : People) { if (filter(person, target)) { count++; } } return count; } }; int main() { Person p1("Alice", 24, 1.80, 'F'), p2("Bob", 18, 1.60, 'M'), p3("Charlie", 30, 1.70, 'M'); Group g; g.People.push_back(p1); g.People.push_back(p2); g.People.push_back(p3); cout << "名为Alice的人数:" << g.getPersonCount(&IsName, "Alice") << endl; cout << "年龄为18的人数:" << g.getPersonCount(&IsAge, 18) << endl; cout << "性别为M的人数:" << g.getPersonCount(&IsGender, 'M') << endl; return 0; }
额外优化:使用Lambda表达式
在C++11及以后的版本中,用Lambda表达式可以更简洁地实现过滤,不需要单独定义过滤函数:
// 在main函数中直接使用Lambda实现自定义过滤 cout << "身高大于1.7的人数:" << g.getPersonCount( [](const Person& p, double h) { return p.getHeight() > h; }, 1.7 ) << endl;
结论
C++完全可以实现通过模板传递过滤函数的功能,核心是让模板适配过滤函数的参数类型,同时注意函数签名匹配、避免不必要的拷贝。Lambda表达式则能进一步简化代码,实现更灵活的过滤逻辑。
内容的提问来源于stack exchange,提问作者Давид Желев
相关产品推荐
相关产品推荐

