Как правильно написать макрос для «расширения» методов родителя?

Нужно создать много наследников от разных типов, все эти типы - наследники QObject и QWidget. Задача наследника - заменить стандартные методы, но оставить возможность обращения к ним (только самому себе). Вот один из классов, который должен "расширить" или подменить методы parent() и setParent():

class PQ_QWidget : public QWidget {
    Q_OBJECT
    PQW_OBJECT

public:
    explicit PQ_QWidget(QWidget* parent = 0) :
        QWidget(parent){
    }

    ~PQ_QWidget(){
        delete this;
    }
};


Сначала я попробовал написать макрос так:
#define PQW_OBJECT \
    Q_PROPERTY( long parent READ parent WRITE setParent ) \
public: \
    Q_INVOKABLE long parent() {\
        return m_parentQPId;\
    }\
public Q_SLOTS:\
    Q_INVOKABLE void setParent(long parentQPId) {\
        QWidget *qo = (QWidget*) ObjectFactory::getQObject(parentQPId);\
        if(qo != NULL) {\
            m_parentQPId = parentQPId;\
            setParent(qo);\
        }\
    }\
private:\
    long m_parentQPId;

на что получил ошибку: invalid conversion from 'QWidget*' to 'long int' > setParent(qo);. С одной стороны логично, что в данном участке кода метод setParent(QObject *) не существует, но с другой - непонятно, почему код макроса пытается "выполнится" на этом этапе, а не на этапе, когда он уже воткнут в реальный класс. И почему не срабатывает перегрузка метода? Ведь у QObject есть публичный метод setParent(QObject *)...

Потом я попробовал заменить setParent(qo) на parent::setParent(qo), на что снова получил ошибку, которая даже не нуждается в комментариях - parent не объявлен.

В итоге вместо parent:: я просто подставил QObject::setParent(qo); - собралось, но не работает. Родитель не меняется.

Рабочий макрос оказался таким:
#define PQW_OBJECT \
    Q_PROPERTY( long parent READ parent WRITE setParent ) \
public: \
    Q_INVOKABLE long parent() {\
        return m_parentQPId;\
    }\
public Q_SLOTS:\
    Q_INVOKABLE void setParent(long parentQPId) {\
        QWidget *qo = (QWidget*) ObjectFactory::getQObject(parentQPId);\
        if(qo != NULL) {\
            m_parentQPId = parentQPId;\
            QWidget::setParent(qo);\
        }\
    }\
private:\
    long m_parentQPId;

Но! Получается, что потомки созданные от QObject, а не от QWidget (пока таких нет, но планируются) не будут менять своего родителя и, скорее всего, вообще будут валить приложение рантайм-ошибкой (не уверен, честно). Так как делать правильно? Создавать два макроса и подставлять нужный в зависимости от какого класса наследуюсь? Или можно все-таки как-то унифицировать это действие?
  • Вопрос задан
  • 458 просмотров
Решения вопроса 1
AxisPod
@AxisPod
Сделайте сначала работающие образцы классов, а затем напилите их на макросы, ну а с другой стороны C++ имеет множественное наследование, в том числе и невиртуальное, почему бы не использовать их. Просто qt не знаю, но как выглядят ваши макросы, уж прямо напрашиваются в отдельные классы-примеси, а какие-то зависимые части можно кинуть и в шаблонный параметр, можно использовать CRTP.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Nipheris
@Nipheris Куратор тега C++
1. Вы пробовали использовать ваш первый вариант без макроса? Что сообщает компилятор? Ошибка из moc-файла прилетает?
2. Я бы посоветовал вам шаблонного родителя, но раз у вас MOC, значит не пойдет.
3. Ну передайте параметр в макрос, раз уж совсем никак. Я бы все-таки разобрался сначала, почему вариант без указания род. класса не работает.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы