对象多重继承

QObject Multiple Inheritance

本文关键字:多重继承 对象      更新时间:2023-10-16

我正在尝试使用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继承自QWidgetSignalInterface,并且两者都继承自QObject。这会引起什么问题吗?

我们知道,如果QObject类是纯虚的,这个问题可以很容易地解决(事实并非如此)。

一个可能的解决方案是:

class Interface: public QWidget {
Q_OBJECT
signals:
void IconChanged(QIcon);
void titleChanged(QString);
}
class Widget1: public Interface {
}

这里的问题是,我已经有很多从QWidget继承的代码,它的痛苦的破解。还有别的办法吗?

不幸的是,继承QObject两次将导致moc出现问题。

从http://qt-project.org

:

如果您正在使用多重继承,moc假定第一个继承的类是QObject的子类。另外,请确保只有第一个继承的类是QObject

我建议使用更像委托模式的东西,或者使用HasA而不是IsA关系重新创建。

Qt允许多重继承,如果基类从QObject私有继承

的例子:

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继承专门为该类。

为什么使用继承,为什么不使用组合?例如,您可以用下面的方式重写案例:

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
    });
}