Qt 多重继承和信号

Posted

技术标签:

【中文标题】Qt 多重继承和信号【英文标题】:Qt multiple inheritance and signals 【发布时间】:2011-03-23 10:27:38 【问题描述】:

由于 QObject,我在使用 QT 时遇到了关于多重继承的问题。我知道很多其他人也有同样的问题,但我不知道该如何解决。

class NavigatableItem : public QObject

    Q_OBJECT

    signals:
        void deselected();
        void selected();
        void activated();
;

class Button : public NavigatableItem, public QToolButton

    Q_OBJECT

    ...


class MainMenuOption : public Button

    Q_OBJECT

    ...

当我这样做时

MainMenuOption* messages = new MainMenuOption();
connect(messages, SIGNAL(selected()), SLOT(onMenuOptionSelected()))

我会得到错误:

QObject' 是 'MainMenuOption' 的模棱两可的基础

我之所以让 NavigatableItem 从 QObject 继承是因为信号。有没有办法做到这一点?

编辑:

为每个继承声明添加 virtual,仍然给我同样的错误:

class NavigatableItem : public virtual QObject

class Button : public virtual NavigatableItem, public virtual QToolButton

class MainMenuOption : public virtual Button

即使在“clean all”、“run qmake”和“build all”之后。

【问题讨论】:

你不能从多个 QObject 子类继承。 QObject只能是其中一个,并且必须是列表中的第一个。 尝试删除那些moc_*,*.obj 文件并重新构建所有文件.. 查看更新的问题。重建并没有解决它。 【参考方案1】:

它需要更多代码,但我过去所做的是将其中一个(在本例中为您的NavigatableItem)制作为纯虚拟类,即接口。不要使用“信号”宏,而是让它们成为纯虚拟保护函数。然后从您的 QObject 派生类以及接口乘以继承,并实现方法。

我知道这有点争议,但不惜一切代价避免多重实现继承确实解决了许多问题和混乱。 Google C++ Style Guidelines 推荐这个,我觉得是个好建议。

class NavigatableItemInterface

    // Don't forget the virtual destructor!
    protected:
        virtual void deselected() = 0;
        virtual void selected() = 0;
        virtual void activated() = 0;
;

class Button : public NavigatableItemInterface, public QToolButton

    Q_OBJECT
    ...
    signals:
        virtual void deselected();
        ...

【讨论】:

感谢 Dave,这就是我同时所做的,所以我至少可以构建项目。然而,一个副作用是,如果我有一个需要成为 NavigatableItem 的 textentry 对象,我必须重新定义每个取消选择/选择和激活的信号。 您必须重新定义它们,但不必重新实现它们。通常有一种方法可以将它们放在某个公共类(可能只是一个实用程序类)中,将其作为继承类的私有成员包含在内,并使您的继承类具有“has-a”关系而不是“is” -a' 关系。是的,这是一些额外的代码,但是您的实际业务逻辑通常可以保存在一个地方,这样您就可以避免“复制和粘贴”错误。我发现避免多重继承的其他问题是值得的,但我很乐意承认这只是一种观点。【参考方案2】:

使用虚拟继承,例如

class X : public virtual Y 

;

class Z : public virtual Y

;

class A : public virtual X, public virtual Z

;

将只有一个基类 Y 的副本

【讨论】:

我在所有继承声明中添加了 virtual,但它仍然给了我同样的错误。 尝试通过运行重新生成 MOC 文件: make distclean; qmake;制作。 查看更新的问题。添加虚拟和重建并没有解决它。 @PoweRoy:因为你不能让QToolButton虚拟继承QObject,所以在这种情况下是行不通的。 class A 的声明中不应有任何virtual。只有 Y 必须虚拟继承,而这正是 PoweRoy不能 做的。【参考方案3】:

你应该使用虚拟继承。

见http://en.allexperts.com/q/C-1040/virtual-inheritance.htm

您似乎遇到了钻石问题,另请参阅:

http://www.cprogramming.com/tutorial/virtual_inheritance.html

这样做:

class NavigatableItem : public virtual QObject
class Button : public virtual NavigatableItem, public virtual QToolButton
class MainMenuOption : public Button

【讨论】:

以上是关于Qt 多重继承和信号的主要内容,如果未能解决你的问题,请参考以下文章

Qt中图元对象的多重集成

QObject 多重继承

Qt中的多重继承

来自两个抽象类的多重继承 (Qt)

Qt、多重继承、包装器或事件过滤器

为啥在多重继承的情况下QObject需要是第一个