Решение этой конкретной проблемы C ++ diamond для классов Qt - PullRequest
0 голосов
/ 17 марта 2019

Я использую класс QT QQuickFramebufferObject, который наследуется от 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,
             ^~~~~~~
/

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

1 Ответ

1 голос
/ 18 марта 2019

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

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

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

Необходимо изменить ReactItem, чтобы он выглядел следующим образом:

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

Класс hiearchy будет выглядеть так:

         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*>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...