A
A
Alexander2015-09-04 05:32:53
Qt
Alexander, 2015-09-04 05:32:53

How to properly typecast in C++\Qt?

There is such a simple header:

#define PQ_OBJECT \
public:\
    QStringList myList;

class PQWidget;
class PQWidget : public QWidget {
    Q_OBJECT
    PQ_OBJECT

public:
    Q_INVOKABLE explicit PQWidget(QWidget *parent = 0)
        : QWidget(parent){}
    virtual ~PQWidget(){}
};

class PQPushButton;
class PQPushButton : public QPushButton {
    Q_OBJECT
    PQ_OBJECT

public:
    Q_INVOKABLE explicit PQPushButton(QWidget *parent = 0)
        : QPushButton(parent) {
        myList << "text1";
        myList << "text2";
    }
};

and code:
// QObject -> PQWidget
    QObject *button = new PQPushButton;
    PQWidget *pbutton = (PQWidget*) button;

    if(pbutton->myList.contains("text1")) {
        qDebug() << "Okay!";
    }

    qDebug() << "QObject -> PQWidget OK!";

everything seems to be written honestly and fairly - PQWidget is a descendant of QWidget , like a button - it is also a descendant of QWidget , QWidget from QObject. And they all have a myList field after my inheritance . The code works. And no matter what widget I write with the addition of the PQ_OBJECT macro , be it various buttons, text fields, containers, and... in short, if you take absolutely any widget, it is perfectly converted into PQWidget and does not show off :)
And here is the second similar case:
class PQObject;
class PQObject : public QObject {
    Q_OBJECT
    PQ_OBJECT

public:
    Q_INVOKABLE explicit PQObject(QObject *parent = 0)
        : QObject(parent){}
    virtual ~PQObject(){}
};

class PQTimer;
class PQTimer : public QTimer {
    Q_OBJECT
    PQ_OBJECT

public:
    Q_INVOKABLE explicit PQTimer(QObject *parent = 0)
        : QTimer(parent) {
        myList << "text1";
        myList << "text2";
    }
};

// QObject -> PQObject
    QObject *timer = new PQTimer;
    PQObject *ptimer = (PQObject*) timer;

    if(ptimer->myList.contains("qwerty")) { // Segmentation fault
        qDebug() << "Okay!";
    }

    qDebug() << "QObject -> PQObject OK!";

Everything is written in exactly the same way as with QWidget. Complete analogy: PQObject and QTimer are descendants of QObject . PQObject and PQTimer have myList fields . At the stage of transformation QObject -> PQObject the program works, but when trying to access any field from PQ_OBJECT - segfault.
Guys, please comment on this behavior? Why does the code work in the first case and not in the second? Was it supposed to work at all or is it a fluke that turned out to be random for all widgets? :)
P.s. I want to note that I cannot inherit from PQObject , as in theory it should have been, because Qt does not allow double inheritance of Q_OBJECT , and my PQObject must be a descendant of QObject .
P.p.s. the macro has been truncated for readability, in fact it has many more fields and methods, and all of them are available (tested) when cast to PQWidget .

Answer the question

In order to leave comments, you need to log in

2 answer(s)
P
Pavel K, 2015-09-04
@PavelK

qmake can't build moc correctly most likely.
Try an explicit cast
QObject * myObj = qobject_cast(PQTimer);

A
Adamos, 2015-09-04
@Adamos

In general, such a cast is a legacy of C, and in C ++ it is bad manners.
If you replace it with dynamic_cast and check the result for NULL, all sorts of nuances may be revealed.
For example, I had problems with casting the parent window to the class that it should have been. The study showed that in the version of the library for one of the platforms, the child class was wrapped in another parent, and such a cast caused a segfault...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question