我正在尝试实现与在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,但我想使用一个实际的实例。有什么简单的方法可以做我正在尝试的事情吗?
或者,我不介意使用函数指针,但我希望我的代码是面向对象的,所以我想避免让非成员函数悬空。
答案 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;
};