简体   繁体   English

为Qt类解决此特定的C ++ Diamond问题

[英]Solving this specific C++ diamond problem for Qt classes

I'm using QT's QQuickFramebufferObject class which inherits from QQuickItem in Qt library. 我正在使用QT的QQuickFramebufferObject类,该类继承自Qt库中的QQuickItem

I have the following user-defined class: 我有以下用户定义的类:

class OpenGlBufferItem: public QQuickFramebufferObject

And I need my OpenGlBufferItem class to also derive from ReactItem . 我需要我的OpenGlBufferItem类也可以从ReactItem派生。 The problem is that ReactItem ultimately derives from QQuickItem too: 问题是ReactItem最终也从QQuickItem派生:

class ReactItem : public QQuickPaintedItem

because QQuickPaintedItem inherits from QQuickItem 因为QQuickPaintedItem继承自QQuickItem

So we have the following problem: 所以我们有以下问题:

           QQuickItem
          /          \
         /            \
QQuickPaintedItem QQuickFramebufferObject
       /                \
   ReactItem        OpenGlBufferItem

What I need is 我需要的是

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

Normally, to solve diamond problems we'd simply declare some classes as virtually inheriting from others. 通常,为了解决钻石问题,我们只需声明某些类实际上是从其他类继承而来。 However, I cannot declare the classes RectItem , QQuickPaintedItem , QQuickFrameBufferObject , because they are already given. 但是,我无法声明类RectItemQQuickPaintedItemQQuickFrameBufferObject ,因为它们已经给出了。

How should I proceed? 我应该如何进行?

UPDATE: 更新:

If I simply tryo to do 如果我只是尝试做

class OpenGlBufferItem: public QQuickFramebufferObject, public ReactItem

I get these kind of errors: 我得到这些错误:

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,
             ^~~~~~~
/

and a lot more 还有更多

This is not possible. 这是不可能的。

I was thinking about using the CRTP (Curiously Recurring Template Pattern), which could theorhetically be employed if you can modify one of the classes and can handle its restrictions. 我正在考虑使用CRTP(好奇地重复模板模式),如果您可以修改其中一个类并可以处理其限制,则可以从理论上使用它。 But it will not work in your case as ReactItem is not deriving directly from QQuickItem, but from QQuickPaintedItem. 但这不适用于您的情况,因为ReactItem不是直接来自QQuickItem,而是直接来自QQuickPaintedItem。

Let's assume that was not the case: 假设情况并非如此:

ReactItem would need to be changed to look like this: ReactItem需要更改为如下所示:

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

The class hiearchy would look like this: 类hiearchy将如下所示:

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

The restrictions of this approach is, that the two ReactItem instantiations are unrelated types with regards to the type hierarchy. 这种方法的限制是,就类型层次结构而言,两个ReactItem实例是不相关的类型。 This means a lot of the code previously referring to ReactItem might needs to be changed. 这意味着以前引用ReactItem的许多代码可能需要更改。

This is quite easy to do for functions: 对于函数,这很容易做到:

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

It is a lot trickier for templated data members like std::vector<ReactItem*> . 对于像std::vector<ReactItem*>这样的模板数据成员来说,这要麻烦std::vector<ReactItem*>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM