使用qSort时遇到问题

时间:2011-11-18 17:32:57

标签: c++ qt qt4

我有这段代码:

QVector<LogEvent *> currentItems;
//add a bunch of LogEvent objects to currentItems
qSort(currentItems.begin(), currentItems.end());

这是我的LogEvent类:

LogEvent.h:

//LogEvent.h
class LogEvent : public QTreeWidgetItem {

public:
    LogEvent();
    LogEvent(QDateTime, LogEvent *parent = 0);
    ~LogEvent();

    bool operator<(const LogEvent *);
    bool operator>(const LogEvent *);
    bool operator<=(const LogEvent *);
    bool operator>=(const LogEvent *);
    bool operator==(const LogEvent *);

private:

    QDateTime timestamp;
};

LogEvent.cpp:

//LogEvent.cpp
LogEvent::LogEvent()
{

}

LogEvent::LogEvent(QDateTime timestamp, LogEvent *parent)
    : QTreeWidgetItem(parent)
{
    this->timestamp = timestamp;
}

bool LogEvent::operator<(const LogEvent * event) {
    return (this->timestamp < event->timestamp);
}

bool LogEvent::operator>(const LogEvent * event) {
    return (this->timestamp > event->timestamp);
}

bool LogEvent::operator<=(const LogEvent * event) {
    return (this->timestamp <= event->timestamp);
}

bool LogEvent::operator>=(const LogEvent * event) {
    return (this->timestamp >= event->timestamp);
}

bool LogEvent::operator==(const LogEvent * event) {
    return (this->timestamp == event->timestamp);
}

排序后,currentItems中的LogEvent对象未正确排序。我很确定我的运算符重载正在运行。

当我做这样的事情时:

std::cout << currentItems[0]<=currentItems[1]?"T":"F";

它将输出正确的值。

那么我做错了什么以及如何纠正呢?

4 个答案:

答案 0 :(得分:7)

qSort正在对指针进行排序,而不是这些指针所指向的对象。如果要使用qSort对LogEvents进行排序,则必须按值而不是通过引用来存储它们(并且还有具有引用的比较运算符,qSort将找不到比较指针函数),或者传递第三个使用您定义的函数的参数。

它可能会解释为什么这样的例子。

LogEvent event1, event2;
LogEvent *eventptr1=&event1,*eventptr2=&event2;
event1<event2; // Operator not defined in your code
event1<eventptr2; // This will call the operator you have defined
eventptr1<eventptr2; // This will compare the pointers themselves, not the LogEvents. The pointers are not dereferenced here.

ETA:为了有一个完整的答案接受,我将从这里的其他答案中剔除一些好的部分。

首先,定义一个小于operator的标准语法:

class LogEvent : public QTreeWidgetItem {

public:
  // ...
  bool operator<(const LogEvent *); // Non-standard, possibly reasonable for use in your own code.
  bool operator<(const LogEvent &); // Standard, will be used by most template algorithms.
  // ...
}

LogEvent.cpp

bool LogEvent::operator<(const LogEvent &event) {return timestamp<event.timestamp;}

完成此操作后,您可以使用此模板取消引用 - 并从leemes的答案中进行比较:

template<class T>
bool dereferencedLessThan(T * o1, T * o2) {
    return *o1 < *o2;
}

按如下方式对列表进行排序:

QVector<LogEvent *> currentItems;
//add a bunch of LogEvent objects to currentItems
qSort(list.begin(), list.end(), dereferencedLessThan<LogEvent>);

为了完整性,为所有比较定义标准语法比较运算符将是一种很好的形式。您是否保留非标准比较运算符取决于您。

答案 1 :(得分:6)

您可以使用两个(通用)指针定义比较函数:

template<class T>
bool dereferencedLessThan(T * o1, T * o2) {
    return *o1 < *o2;
}

然后致电

void qSort ( RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan )

像这样:

qSort(list.begin(), list.end(), dereferencedLessThan<LogEvent>);

然后,您可以将此方法用于其他类型,而无需定义多个函数。

答案 2 :(得分:4)

比较运算符不应该使用const引用而不是指针吗?

在最后一个片段中,您要比较地址,而不是值。

答案 3 :(得分:0)

qSort函数需要项类型(在上面的例子中,LogEvent)来实现运算符&lt;()。 像这样:

bool LogEvent::operator<(const LogEvent& event) {
    return timestamp < event.timestamp;
}