Есть вот такой незамысловатый 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";
}
};
и код:
// QObject -> PQWidget
QObject *button = new PQPushButton;
PQWidget *pbutton = (PQWidget*) button;
if(pbutton->myList.contains("text1")) {
qDebug() << "Okay!";
}
qDebug() << "QObject -> PQWidget OK!";
вроде написано всё честно и справедливо -
PQWidget является потомком
QWidget, как и кнопка. И все они после моего наследования имеют поле
myList. Код работает. И какой бы виджет я не писал с добавлением макроса
PQ_OBJECT, будь то различные кнопки, текстовые поля, контейнеры и... короче, если взять абсолютно любой виджет, он прекрасно преобразуется в
PQWidget и не выпендривается
А вот второй похожий случай:
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!";
Все написано в точности так же как и с
QWidget. Полная аналогия:
PQObject и
QTimer - потомки
QObject.
PQObject и
PQTimer имеют поле
myList. На этапе преобразования
QObject -> PQObject программа работает, но при попытке обратится к какому либо полю из
PQ_OBJECT - сегфолт.
Ребята, прокомментируйте, пожалуйста, такое поведение? Почему в первом случае код работает, а во втором - нет? Должен ли он вообще был работать или это случайность, которая оказалась случайной для всех виджетов?
П.с. хочу заметить, что унаследоваться от
PQObject , как по идее и должно было быть, я не могу, потому что Qt не допускает двойное наследование
Q_OBJECT, а мой
PQObject обязательно должен быть наследником
QObject.
П.п.с. макрос обрезал для читаемости, на самом деле в нем намного больше полей и методов и все они доступны (проверено) при приведении к PQWidget.