我创建了一个带有student
子类的类comparator
。 comparator
的构造函数采用一个名为cmp_mode
的参数,指定我们应该如何比较学生。
class student
{
public:
std::string name;
int course, group;
student(std::string name,
int course,
int group): name(name)
{
this->course = course;
this->group = group;
}
enum cmp_mode
{
NAME,
COURSE,
GROUP
};
class comparator
{
cmp_mode mode;
public:
comparator(cmp_mode mode)
{
this->mode = mode;
}
bool compare(student s1, student s2)
{
if (mode == NAME)
return s1.name < s2.name;
else if (mode == COURSE)
return s1.course < s2.course;
else if (mode == GROUP)
return s1.group < s2.group;
else
throw "Oh god! We can't compare variables using these keys!";
}
};
};
另外,我创建了list
students
,现在我想使用比较器子类对此列表进行排序。
std::list<student> l;
student st1("Anya", 2, 5);
student st2("Misha", 4, 2);
student st3("Yasha", 1, 3);
l.push_back(st1);
l.push_back(st2);
l.push_back(st3);
student::comparator by_group(student::GROUP);
l.sort(by_group.compare);
但是我收到了以下错误。
ERROR: Reference to non-static member function must be called.
那我该怎么办?如何以更好的方式调整排序?
答案 0 :(得分:3)
我从你的评论开始:
我认为我可以为每个案例编写比较函数,但看起来更糟。
为什么更糟?我个人认为运行速度更快(编译速度更快),维护更简单(功能更短)。
这写起来不是那么简单:
l.sort(student::compare_by_group);
这种实施更容易维护:
class student
{
...
static bool compare_by_name(const student& s1, const student& s2)
{
return s1.name < s2.name;
}
static bool compare_by_course(const student& s1, const student& s2)
{
return s1.course < s2.course;
}
static bool compare_by_group(const student& s1, const student& s2)
{
return s1.group < s2.group;
}
// Add the followings only if you really need this stuff
// e.g. to get comparator type from elsewhere
enum cmp_mode
{
NAME,
COURSE,
GROUP
};
static bool compare(cmp_mode, const student& s1, const student& s2)
{
switch(cmp_mode) {
case NAME: return compare_by_name(s1, s2);
...
}
}
};
答案 1 :(得分:2)
非静态成员函数具有函数所属类型的隐式参数。他们需要这种类型的实例才能工作。如果您没有C ++ 11支持,可以使用std::bind
(或boost.bind
)将student::comparator
对象“绑定”到比较函数的第一个参数:
student::comparator by_group(student::GROUP);
using namespace std::placeholders;
auto comp = std::bind(student::comparator::compare, &by_group, _1, _2);
l.sort(comp);
在上面的代码中,by_group
对象被绑定为student::comparator::compare
函数的第一个参数,生成的函数对象获取两个student
对象并返回bool
:
std::cout << std::boolalpha;
const student& s1 = l[0];
const student& s2 = l[1];
std::cout << comp(s1, s2) << "\n"; // prints "true" or "false".
我还建议您将比较成员函数的签名更改为
bool compare(const student& s1, const student& s2) const;
没有理由按值传递,并且成员函数没有理由不是const
。
答案 2 :(得分:2)
像Piotr一样,我建议为每个属性编写比较器,这样比较快,不易出错。但是,我建议使用仿函数对象而不是静态函数:
struct compare_by_name {
bool operator()(const student& a, const student& b) const {
return a.name < b.name;
}
};
如果您只需要比较器一次或两次,并且您使用的是C ++ 11,那么更喜欢内联lambda:
l.sort([](const student& a, const student& b){ return a.name < b.name; });
如果您绝对需要动态比较器,请将其写为普通仿函数对象,即定义operator()
:
bool operator()(const student& a, const student& b) const {
switch (mode) {
case NAME:
return a.name < b.name;
// No default case, the constructor (if at all) should check whether the mode
// is valid.
}
}