Решение этой конкретной проблемы алмаза C++ для классов Qt

Я использую класс QQuickFramebufferObject QT, который наследуется от QQuickItem в библиотеке Qt.

У меня есть следующий пользовательский класс:

class OpenGlBufferItem: public QQuickFramebufferObject

И мне нужно, чтобы мой класс OpenGlBufferItem также производился от ReactItem. Проблема в том, что ReactItem тоже происходит от QQuickItem:

class ReactItem : public QQuickPaintedItem

потому что QQuickPaintedItem наследуется от QQuickItem

Итак, имеем следующую проблему:

           QQuickItem
          /          \
         /            \
QQuickPaintedItem QQuickFramebufferObject
       /                \
   ReactItem        OpenGlBufferItem

Мне нужно

           QQuickItem
          /          \
         /            \
QQuickPaintedItem QQuickFramebufferObject
       /                \
   ReactItem            /
       \               /
        \             /
        OpenGlBufferItem

Обычно для решения проблем с ромбами мы просто объявляем одни классы виртуально наследованием других. Однако я не могу объявить классы RectItem, QQuickPaintedItem, QQuickFrameBufferObject, потому что они уже заданы.

Как мне поступить?

ОБНОВЛЕНИЕ:

Если я просто попытаюсь сделать

class OpenGlBufferItem: public QQuickFramebufferObject, public ReactItem

Я получаю такие ошибки:

Command failed: ./build.sh -e "modules/mediaplayer/desktop"
In file included from /home/lz/orwell/orwellJS/desktop/modules/mediaplayer/desktop/orwell_subdir/orwell_autogen/EWIEGA46WW/moc_OpenGlBufferQtQuick.cpp:9:0,
                 from /home/lz/orwell/orwellJS/desktop/modules/mediaplayer/desktop/orwell_subdir/orwell_autogen/mocs_compilation.cpp:2:
/home/lz/orwell/orwellJS/desktop/modules/mediaplayer/desktop/orwell_subdir/orwell_autogen/EWIEGA46WW/../../../../../../../../OpenGlBufferQtQuick.h: In constructor ‘OpenGlBufferItem::OpenGlBufferItem(QQuickItem*)’:
/home/lz/orwell/orwellJS/desktop/modules/mediaplayer/desktop/orwell_subdir/orwell_autogen/EWIEGA46WW/../../../../../../../../OpenGlBufferQtQuick.h:90:13: error: reference to ‘connect’ is ambiguous
             connect(parent, SIGNAL(widthChanged()), this, SLOT(parentWidthChanged()));
             ^~~~~~~
In file included from /home/lz/Qt5.11.2/5.11.2/gcc_64/include/QtCore/QObject:1:0,
                 from /home/lz/orwell/orwellJS/desktop/modules/mediaplayer/desktop/orwell_subdir/orwell_autogen/EWIEGA46WW/../../../../../../../../OpenGlBufferQtQuick.h:3,
                 from /home/lz/orwell/orwellJS/desktop/modules/mediaplayer/desktop/orwell_subdir/orwell_autogen/EWIEGA46WW/moc_OpenGlBufferQtQuick.cpp:9,
                 from /home/lz/orwell/orwellJS/desktop/modules/mediaplayer/desktop/orwell_subdir/orwell_autogen/mocs_compilation.cpp:2:
/home/lz/Qt5.11.2/5.11.2/gcc_64/include/QtCore/qobject.h:308:13: note: candidates are: template<class Func1, class Func2> static typename std::enable_if<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1), QMetaObject::Connection>::type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const QObject*, Func2, Qt::ConnectionType)
             connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
             ^~~~~~~
/home/lz/Qt5.11.2/5.11.2/gcc_64/include/QtCore/qobject.h:300:13: note:                 template<class Func1, class Func2> static typename std::enable_if<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1), QMetaObject::Connection>::type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, Func2)
             connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
             ^~~~~~~
/home/lz/Qt5.11.2/5.11.2/gcc_64/include/QtCore/qobject.h:269:13: note:                 template<class Func1, class Func2> static typename std::enable_if<(((int)(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0) && (! QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction)), QMetaObject::Connection>::type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const QObject*, Func2, Qt::ConnectionType)
             connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
             ^~~~~~~
/

и многое другое


person Lucas Zanella    schedule 17.03.2019    source источник


Ответы (1)


Это невозможно.

Я думал об использовании CRTP (любопытно повторяющегося шаблона шаблона), который теоретически можно использовать, если вы можете изменить один из классов и справиться с его ограничениями. Но в вашем случае это не сработает, поскольку ReactItem не является производным непосредственно от QQuickItem, а происходит от QQuickPaintedItem.

Предположим, что это не так:

ReactItem нужно будет изменить, чтобы он выглядел так:

template <class T> class ReactItem : public T {/*...*/};

Иерархия классов будет выглядеть так:

         QQuickItem
        /           \
       /        QQuickFramebufferObject
      /               \
ReactItem<QQuickItem>  \
                        \
                   ReactItem<QQuickFramebufferObject>
                        /
               OpenGlBufferItem

Ограничения этого подхода заключаются в том, что два экземпляра ReactItem являются несвязанными типами в отношении иерархии типов. Это означает, что большую часть кода, ранее ссылавшегося на ReactItem, возможно, потребуется изменить.

Это довольно легко сделать для функций:

void f(ReactItem* item) { item->setVisible(true); }
// becomes
template<class T> void f(ReactItem<T>* item)  { item->setVisible(true); }

Это намного сложнее для шаблонных элементов данных, таких как std::vector<ReactItem*>.

person smerlin    schedule 17.03.2019
comment
Вы уверены, что нет волшебного способа заставить мой элемент реализовать методы reactItem? - person Lucas Zanella; 20.03.2019