2011-03-23 757 views
6

由於QObject,我在QT中遇到了關於多重繼承的問題。我知道很多其他人也有同樣的問題,但我不知道該如何解決。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' is an ambiguous base of 'MainMenuOption'

我之所以讓因爲信號的自QObject NavigatableItem enherit。有沒有辦法做到這一點?

編輯:

添加虛擬到每個的傳承聲明,仍然給我相同的錯誤:

class NavigatableItem : public virtual QObject 

class Button : public virtual NavigatableItem, public virtual QToolButton 

class MainMenuOption : public virtual Button 

即使在一個「乾淨所有」,「運行的qmake」和「建立所有」 。

+5

不能從多個繼承QObject子類。其中只有一個可以是QObject,它必須是列表中的第一個。 – 2011-03-23 10:47:14

+1

嘗試刪除這些'moc_ *','* .obj'文件並重建所有文件。 – liaK 2011-03-23 11:58:18

+0

查看更新後的問題。重建沒有解決它。 – RvdK 2011-03-23 13:38:04

回答

8

它需要更多的代碼,但我在過去做的是讓他們的一個(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(); 
     ... 
} 
+0

感謝戴夫,這是我所做的,所以我至少可以建立這個項目。然而,一個副作用是,如果我有一個textentry對象需要成爲NavigatableItem,我必須重新定義每個被取消選擇/選定和激活的信號。 – RvdK 2011-03-23 13:40:07

+2

你將不得不重新定義它們,但你不應該重新實現它們。通常有一種方法可以將這些放在一些普通的類(也許只是一個實用類)中,將其作爲繼承類的私有成員,並使您的繼承類具有「有-α」關係而不是「是」 '關係'。是的,這是一些額外的代碼,但是您的實際業務邏輯通常可以保存在一個地方,以避免「複製和粘貼」錯誤。我發現避免多繼承的其他問題是值得的,但我很樂意承認這只是一種意見。 – 2011-03-23 15:20:59

1

使用虛擬繼承,例如

class X : public virtual Y 
{ 
}; 

class Z : public virtual Y 
{ 
}; 

class A : public virtual X, public virtual Z 
{ 
}; 

只會有基類的一個副本Ÿ

+0

我添加虛擬所有繼承聲明,但它仍然給了我相同的錯誤。 – RvdK 2011-03-23 10:56:47

+1

嘗試通過運行重新生成MOC文件:make distclean; QMAKE;使。 – Tobias 2011-03-23 11:28:48

+0

查看更新的問題。添加虛擬和重建不能解決它。 – RvdK 2011-03-23 13:38:25