QObject 多重继承
Posted
技术标签:
【中文标题】QObject 多重继承【英文标题】:QObject Multiple Inheritance 【发布时间】:2012-01-24 14:32:39 【问题描述】:我正在尝试在 C++/Qt 的类中使用混合来提供一大堆具有通用界面的小部件。接口是这样定义的,如果它被定义为其他小部件类的基类,那么小部件本身就会有这些信号:
class SignalInterface: public QObject
Q_OBJECT
public:
SignalInterface();
virtual ~SignalInterface();
signals:
void iconChanged(QIcon);
void titleChanged(QString);
class Widget1: public SignalInterface, QWidget
public:
Widget1()
virtual ~Widget1()
// The Widget Should Inherit the signals
查看类层次结构,问题变得很明显,我偶然发现了多重继承中可怕的菱形,其中Widget1
继承自QWidget
和SignalInterface
,两者都继承自QObject
。这会导致任何问题吗?
我们知道,如果QObject
类是纯虚拟的(事实并非如此),这个问题就可以轻松解决。
一个可能的解决方案是:
class Interface: public QWidget
Q_OBJECT
signals:
void IconChanged(QIcon);
void titleChanged(QString);
class Widget1: public Interface
这里的问题是我已经有很多从 QWidget
继承的代码,并且很难破解它。还有其他方法吗?
【问题讨论】:
看看:***.com/questions/17943496/… 我遇到了这个问题,只是添加了一个信号发射器作为基接口的成员,而不是它的基类。 【参考方案1】:很遗憾,两次继承QObject
会导致moc
出现问题。
来自http://qt-project.org:
如果您使用多重继承,moc 假定第一个 继承类是QObject的子类。此外,请确保只有 第一个继承的类是 QObject。
我建议使用更像委托模式的东西,或者使用 HasA 而不是 IsA 关系重新创建。
【讨论】:
请注意,对于 Qt5,此规则保持不变:doc.qt.io/qt-5/…(您提供了 Qt4 文档的链接) (在 2011 年问及回答这个问题时,Qt5 还不存在)【参考方案2】:如果基类私有地从 QObject 继承,Qt 允许多重继承。
例子:
class Base: private QObject
Q_OBJECT
/*Can use signals and slots like any other QObject-derived class*/
;
class Derived1: public Base
/*Cannot use signals/slots because it does not "see" that Base inherits from QObject*/
;
class Derived2: public QWidget, public Base
Q_OBJECT
/*Can use signals/slots plus has all the functionality of QWidget and Base*/
;
当然,私有继承完全是另一种动物,可能无法为您提供真正需要的解决方案。我使用它的目的是当我只能在基类中使用信号/插槽时。当我确实需要派生类中的QObject
行为时,我从QObject
继承,专门用于该类。
【讨论】:
使用 Qt5.9,此解决方案在编译 moc 生成的文件时出错:'static_cast': ambiguous conversions from 'QObject *' to 'myClass *'【参考方案3】:为什么使用继承,为什么不使用组合? 例如,您可以通过以下方式重写您的案例:
class IMyWidgetSignals : public QObject
Q_OBJECT
signals:
void iconChanged(QIcon);
void titleChanged(QString);
;
//------------------------------------------------------------------------------
class IMyWidget
public:
IMyWidget ()
// virtual functions:
// ...
IMyWidgetSignals _signals;
;
//------------------------------------------------------------------------------
class Widget1: public QWidget, public IMyWidget
public:
using QWidget::QWidget;
//------------------------------------------------------------------------------
int main(...)
Widget1 w1;
w1.show();
QObject::connect(&w1._signals, &IMyWidgetSignals::iconChanged, [] (const auto &icon)
// ... do smth with icon
);
【讨论】:
顺便说一句,KDAB 开发人员提出了一种新的信号/槽/属性机制,它不需要任何 QObject 的东西,可能是一个解决方案。 kdab.com/signals-slots-properties-bindings以上是关于QObject 多重继承的主要内容,如果未能解决你的问题,请参考以下文章