用排序函子实现多态性

时间:2015-11-02 11:57:52

标签: c++ comparator functor

我正在尝试实现与在Java中使用比较器类似的东西。我希望能够在对象中保存排序策略作为实例变量,我可以将其赋予list.sort()

我目前的尝试(不起作用):

struct strategy {
    virtual bool compare(const int* pro1, const int* pro2) = 0;
    bool operator()(const int* pro1, const int* pro2) {
        return compare(pro1, pro2);
    };
};

struct myComp : public strategy{

    bool compare(const int* pro1, const int* pro2) {
        return *pro1 > *pro2;
    }
};

int main() {
    strategy * s = new myComp();

    list<int *> l;
    int a1 = 1;
    int a2 = 2;
    l.push_front(&a1);
    l.push_front(&a2);

    l.sort((*s));

    for (list<int*>::iterator it = l.begin(); it != l.end(); ++it)
        cout << **it << endl;

    return 0;
}

大概是因为...当我直接使用myComp时,我只使用实际的类名myComp,但我想使用一个实际的实例。有什么简单的方法可以做我正在尝试的事情吗?

或者,我不介意使用函数指针,但我希望我的代码是面向对象的,所以我想避免让非成员函数悬空。

1 个答案:

答案 0 :(得分:1)

您遇到的问题是,std::list::sort会获取strategy类型的副本(请参阅reference),这会导致切片。答案是:不要混合模板化函数调用和虚拟继承。比较相同类型的两个比较器不必在这种方法中相关,如果它们仍然需要指定实现类,而不是基类。

在您的情况下替换

strategy * s = new myComp();
...
l.sort((*s));

...
l.sort(myComp());

为了提高性能,您不应该提供比较每个项目的虚拟函数,而应该考虑哪个系统正在进行排序,而是在该系统上实现虚拟调用:

class SystemBase {
protected:
    ...
    virtual void Prepare(std::list<int>& list) const = 0;
};

或委托:

class System {
public:
     class SystemOperator {
     public:
          virtual void Prepare(std::list<int>& list) = 0;
          virtual void Compute(std::list<int>& list) = 0;
     };

     void SetOperator(std::unique_ptr<SystemOperator> op) { m_operator = std::move(op); }

private:
     std::unique_ptr<SystemOperator> m_operator;
};