27

I'm trying to create more useful debug messages for my class where store data. My code is looking something like this

#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;
}

I expect qDebug() << model will print "Hello world!". However, there is alway something like "QAbstractTableModel(0x1c7e520)" on the output.

Do you have any idea what's wrong?

izidor
  • 4,068
  • 5
  • 33
  • 43
  • 3
    1. it looks like Qt wants the stream operator to be: QDebug operator<<(QDebug dbg, const DataModel &model) [namely returning & passing QDebug by value], see http://doc.trolltech.com/4.6/debug.html#providing-support-for-the-qdebug-stream-operator 2. you have declared it like: friend QDebug & operator<< (const QDebug &d, DataModel model); but defined it withouth the const: QDebug & operator<< (QDebug &d, DataModel model) [althought it's probably just a copy/paste error - your code it shouldn't link] – Eugen Constantin Dinca Apr 20 '10 at 18:33

5 Answers5

33

I know it long time now, but just to be documented and to help any other people who eventually come here having the same doubt, the easiest way to get qDebug() << working with your own class printing something like "Hello World" or whatever else, is to implement implicit conversion of your class to a printable type, like QString (which is well supported by QDebug).

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

};
Vinícius A. Jorge
  • 731
  • 1
  • 6
  • 9
  • 4
    This is much more useful and manageable than overloading `<<`. Thanks! – Ayberk Özgür Apr 28 '16 at 15:13
  • 2
    Thinking about this question, the first solution in this topic (overloading operator<<) will be the only solution IF the class you want to print is a third-party one. If the class implementation is yours, my approach is far simpler than the other. – Vinícius A. Jorge May 04 '16 at 13:22
  • This is very useful and exactly what I was looking for. I'm surprised it's not in the official documentation. – Albin Stigo Apr 20 '17 at 12:14
  • Can someone share a simple example of how to use that ? This result in an error to me. ``` error: invalid operands to binary expression ('QDebug' and 'const LinkConfiguration') qCCritical(PING_PROTOCOL_SENSOR) << "Connection fail !" << conConf << link()->errorString();; ``` – Patrick José Pereira Aug 15 '18 at 20:07
  • 5
    It can be dangerous to have an implicit conversion operator to `QString`. For example it enables something like that: `QVariant( myFooInstance )` but instead of storing a `Foo` instance, it converts it to `QString` and stores that. – Ignitor Apr 03 '19 at 15:10
  • @Ignitor, that's a good point I've never tought. I've never stored custom class instances into a QVariant object, just pointers. – Vinícius A. Jorge Apr 25 '20 at 00:34
  • This solution doesn't work with inheritance. I.e. I can't override (tried also with virtual) the base class's implementation and have the derived class be called using polymorphism. – MathCrackExchange Aug 02 '21 at 00:15
15

In your example, qDebug() prints the address of your variable, which is the default behavior for unknown types.

In fact, there seem to be two things you have to take care of:

  • Get the item by value (and eugen already pointed it out!).
  • Define the overloading operator before you use it, put its signature in the header file, or define it as forward before using it (otherwise you will get the default "qDebug() <<" behavior).

This will give you:

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

or

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

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

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

I've learned it the hard way, too...

a.l.e
  • 699
  • 6
  • 4
12

After an hour of playing with this question I figured out model is pointer to DataModel and my operator << takes only references.

izidor
  • 4,068
  • 5
  • 33
  • 43
  • 2
    Sorry, can you please extend your answer a little bit further? Im trying to achieve the same but I cant. Thanks in advance – David Sánchez May 12 '15 at 02:54
  • This means when your signature is `QDebug operator<< (QDebug d, const DataModel &model)`, it's not the same to pass a `DataModel` or a `DataModel*`. The initial result `QAbstractTableModel(0x1c7e520)` a pointer and use the appropriate operator, not the one defined in the example. – Alexis Sep 17 '18 at 13:12
  • If the operator takes only references and your `DataModel` instance is stored in a pointer, when calling the function, you can just dereference your pointer to pass a reference. When calling qDebug you can do this: `qDebug() << *model;` – Vinícius A. Jorge Apr 25 '20 at 00:31
9

You implemented only the << operator for a reference. If your model variable is a pointer, it will use another implementation (not yours).

To use your implementation you can do:

qDebug() << *model

By the way, the correct way to implement a QDebug operator<<(QDebug dbg, const T &data) overload is to use the QDebugStateSaver class:

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

In this way the settings (i.e. wether to insert or not spaces between prints) will be correctly restored when exiting the function.

Mr. Developerdude
  • 9,118
  • 10
  • 57
  • 95
fferri
  • 18,285
  • 5
  • 46
  • 95
3

I found this answer on the QT Forum by raven-worx (giving credit where credit is due!)

In the .h file:

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

where MyType is your class, like DataModel and type is the instance you will display.

And in the .cpp file:

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

and you can use the QDebug's space(), nospace(), and other methods to control the exact display of the stream.

So for the OP, we would use:

// 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;
  • a bit odd follow up... but how can you access private parts of class with this approach? Say `stram< – Dariusz Aug 31 '20 at 16:08