Getting the name of sub class within super class in Qt

2.9k views Asked by At

I have a base class that is inherited by two sub classes. All three classes use qDebug() to do some debug printing and Q_FUNC_INFO to identify the source of the print. The problem is that when printing from the base class, Q_FUNC_INFO contains the name of the base class, making it impossible to know which of the two sub classes the instance represents.

The best solution I have come up with so far is using a QString variable instead of Q_FUNC_INFO at the base class and supplying it with the correct name when instantiating.

Are there any other, more preferable solutions?

1

There are 1 answers

1
László Papp On BEST ANSWER

Are there any other, more preferable solutions?

In general, no, that is fine. In such cases, you would need to place the Q_FUNC_INFO into the subclass if that is possible. If not, you are out of luck, but... please read on.

Qt internally also uses explicit strings rather than Q_FUNC_INFO, I believe partially for this reason.

For QObjects, you could use the meta object compiler for some introspection to get the real name dynamically, namely:

const char * QMetaObject::className() const

Returns the class name.

and

const QMetaObject * QObject::metaObject() const [virtual]

Returns a pointer to the meta-object of this object.

A meta-object contains information about a class that inherits QObject, e.g. class name, superclass name, properties, signals and slots. Every QObject subclass that contains the Q_OBJECT macro will have a meta-object.

The meta-object information is required by the signal/slot connection mechanism and the property system. The inherits() function also makes use of the meta-object.

If you have no pointer to an actual object instance but still want to access the meta-object of a class, you can use staticMetaObject.

You also take a look into this when dealing with constructors as your comment seems to indicate it:

QMetaMethod QMetaObject::constructor(int index) const

Returns the meta-data for the constructor with the given index.

main.cpp

#include <QObject>
#include <QDebug>

class Foo : public QObject
{
    Q_OBJECT
    public:
        virtual void baz() {  qDebug() << "Class name:" << metaObject()->className(); }
};

class Bar : public Foo
{
    Q_OBJECT
};

#include "main.moc"

int main()
{
    Bar bar;
    bar.baz();
    return 0;
}

Output

moc main.cpp -o main.moc && g++ -Wall -I/usr/include/qt -I/usr/include/ -I/usr/include/qt/QtCore -lQt5Core -fPIC main.cpp && ./a.out

Class name: Bar

Note: if you would like to get this mechanism work in the constructor, the simple answer is that you cannot. Nothing will really help you there. That is due to the fact how inheritance is handled in C++. First, the base class is constructed, and at that stage, the subclass is yet fully constructed (strictly speaking, not even the base), so you cannot really get more information about it without explicitly making sure with an additional argument to the base class constructor. But then, you would get a bloated API just for this simple thing. I would suggest in such a case to just put the print into the subclasses as opposed to the base classes.