使用qSort有困难

Having trouble using qSort

本文关键字:qSort 使用      更新时间:2023-10-16

我有这样的代码:

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";

它将输出正确的值

那么我做错了什么,我如何纠正它?

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

为完整起见,最好为所有比较定义标准语法比较操作符。是否保留非标准比较运算符取决于您。

可以定义一个接受两个(泛型)指针的比较函数:

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

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

比较操作符不应该接受const引用,而不是指针吗?

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

qSort函数需要项目类型(在上面的例子中是LogEvent)来实现operator<()。像这样:

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