非静态函数作为C ++中另一个函数的参数

时间:2012-09-30 06:57:23

标签: c++

我创建了一个带有student子类的类comparatorcomparator的构造函数采用一个名为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.

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

3 个答案:

答案 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.
  }
}