1

student用 subclass做了一个类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!";
        }
    };

};

另外,我创建了一个listof 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.

所以我该怎么做?如何以更好的方式调整排序?

4

3 回答 3

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);
          ...
        }
    } 

};
于 2012-09-30T10:31:21.177 回答
2

非静态成员函数具有该函数所属类型的隐式参数。他们需要这种类型的实例才能工作。您可以使用std::bind(或者boost.bind如果您没有 C++11 支持)将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

于 2012-09-30T07:10:08.847 回答
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.
  }
}
于 2012-09-30T10:49:43.703 回答