Подтвердить что ты не робот

Как перегрузить оператор << для qDebug

Я пытаюсь создать более полезные отладочные сообщения для моего класса, где хранятся данные. Мой код выглядит примерно так.

#include <QAbstractTableModel>
#include <QDebug>

/**
  * Model for storing data. 
  */
class DataModel : public QAbstractTableModel {
    // for debugging purposes
    friend QDebug operator<< (QDebug d, const DataModel &model);

    //other stuff
};

/**
  * Overloading operator for debugging purposes
  */
QDebug operator<< (QDebug d, const DataModel &model) {
    d << "Hello world!";
    return d;
}

Я ожидаю, что qDebug() << model напечатает "Hello world!". Однако на выходе есть что-то вроде "QAbstractTableModel (0x1c7e520)".

Есть ли у вас какое-то представление о том, что случилось?

4b9b3361

Ответ 1

После часа игры с этим вопросом я понял, что model является указателем на DataModel, а мой оператор << принимает только ссылки.

Ответ 2

Я знаю это долгое время, но для того, чтобы быть документированным и помогать любым другим людям, которые в конечном итоге приходят сюда с такими же сомнениями, самый простой способ получить qDebug() < работа с вашим собственным типом печати, например, "Hello World" или что-то еще, заключается в том, чтобы реализовать неявное преобразование вашего класса в печатный тип, например QString (который хорошо поддерживается QDebug).

class Foo {
public:
   Foo() { }
   operator QString() const { return <put your QString here>; }   

};

Ответ 3

В вашем примере qDebug() печатает адрес вашей переменной, который является поведением по умолчанию для неизвестных типов.

На самом деле, по-видимому, вам нужно позаботиться о двух вещах:

  • Получить элемент по значению (и евген уже указал на это!).
  • Определите оператор перегрузки перед его использованием, поместите его подпись в файл заголовка или определите его как forward перед его использованием (в противном случае вы получите поведение qDebug() < "по умолчанию).

Это даст вам:

QDebug operator<< (QDebug d, const DataModel &model) {
    d << "Hello world!";
    return d;
}
DataModel m;
qDebug() << "m" << m;

или

QDebug operator<< (QDebug d, const DataModel &model);

DataModel m;
qDebug() << "m" << m;

QDebug operator<< (QDebug d, const DataModel &model) {
    d << "Hello world!";
    return d;
}

Я тоже научился этому...

Ответ 4

Я нашел этот ответ на форуме QT на raven-worx (предоставляя кредит, где кредит должен быть!)

В файле .h:

QDebug operator<<(QDebug dbg, const MyType &type);

где MyType - ваш класс, например DataModel и type - это экземпляр, который вы покажете.

И в файле .cpp:

QDebug operator<<(QDebug dbg, const MyType &type)
{
    dbg.nospace() << "MyType(" << .... << ")";
    return dbg.maybeSpace();
}

и вы можете использовать QDebug space(), nospace() и другие методы для управления точным отображением потока.

Итак, для OP мы будем использовать:

// in the .h file:
class DataModel : public QAbstractTableModel {
// stuff
};
QDebug operator<<(QDebug dbg, const DataModel &data);

// in the .cpp file:
QDebug operator<<(QDebug dbg, const DataModel &data)
{
    dbg.nospace() << "My data {" << data.someField << ',' << data.another << "}";
    return dbg.maybeSpace();
}

// in some .cpp user of the class:
DataModel myData;

. . .

QDebug() << "The current value of myData is" << myData;

Ответ 5

Вы внедрили только < оператора для справки. Если ваша переменная model указатель, она будет использовать другую реализацию (а не вашу).

Чтобы использовать вашу реализацию, вы можете:

qDebug() << *model

Кстати, правильным способом реализации перегрузки QDebug operator<<(QDebug dbg, const T &data) является использование класса QDebugStateSaver:

QDebug operator<<(QDebug dbg, const QDataflowModelOutlet &outlet)
{
    QDebugStateSaver stateSaver(dbg);
    dbg.nospace() << ...;
    return debug;
}

Таким образом, при выходе из функции будут корректно восстановлены настройки (то есть, чтобы вставить или не удалять промежутки между отпечатками).