2010-11-04 104 views
2

如果我有一個Container類,它持有一堆Component對象(類似於Java的UI框架),那麼跟蹤每個Component中的父親Container的風格/練習是不是很差?使用共依賴類是不好的做法嗎?

這最終導致一些奇怪的編譯器問題,因爲Component包含Container的頭文件,反之亦然。即使有一個頭文件保護修復,我最終不得不在Container首部的開頭聲明一個原型class Component;,並且類似地對於Component

好像你必須要經過相當多的麻煩讓兩個類之間的雙向互動。尋求解決共存依賴「解決」的問題的另一種解決方案,還是C++期望的這種複雜的實現方式,我應該吸取它?

編輯:也許一些背景/推理會有所幫助。我使用這種協同依賴的原因是因爲我需要在調用子進程的析構函數時通知父進程(因此可以從子進程列表中刪除它),並且還需要獲取子進程的位置是相對於父母的。

感謝,
Jengerer

+0

我刪除的C代碼,因爲這的確是一個C++的問題。 – 2010-11-04 04:40:01

+0

對我來說,GUI標籤也不是很合適 - 會讓Jengerer重新考慮這一點。 – 2010-11-04 04:46:35

+0

好吧,'Component'和'Container'類是我用C++編寫的一個GUI。但我同意這不是所有必要的。 – Jengerer 2010-11-04 04:48:08

回答

2

其實我認爲這是一個設計問題。你真的應該看看整個設計,看看你是否可以更好地設計它。問自己爲什麼你有需要訪問容器的依賴類。也許容器正在提供它不應該的功能。這個功能可以以另一種方式提供嗎?

+0

我試圖用這種設計解決的主要問題是: a)當一個'Component'被銷燬時,我想通知父母它應該從兒童列表中刪除。 b)當一個「組件」被繪製到屏幕上時,我希望它相對於父母的位置繪製自己。 如何解決這些問題而不使用這些相關類?我無法真正想到一種比這更簡潔的方式。 – Jengerer 2010-11-04 04:50:28

+1

嗯,首先 - 哪裏是破壞組件的代碼?也許這應該是容器的一個功能,這樣它既可以刪除組件,也可以將它從本地列表中刪除。和draw函數一樣。容器繪製函數可以指示每個組件繪製,給它一個x/y位置以開始。換句話說,對於刪除和繪製函數,爲什麼不把容器作爲主要入口點?另一種選擇是使用觀察者模式來查看返回容器的引用是否通過接口。 – drekka 2010-11-04 04:59:24

+0

好主意,我想我最終可能會接受這個建議。我實際上考慮過在外部設置孩子的位置,但是我猶豫了,因爲我不喜歡每次計算它,但是我意識到這基本上已經是我的程序所做的,只有位置是在孩子中計算的。 – Jengerer 2010-11-04 05:05:53

2

這是一般最好不要有這樣的循環依賴:他們是一個有點疼痛代碼,阻撓有關代碼,可測試性等邏輯推理..

他們無論如何都可以輕鬆避免 - 您可以在組件中保留一些仿函數,然後將它們指向適用於正在處理的事件的Container操作,或者從抽象接口派生Container,以便組件可以有一個指向它的容器和Container從中導出。或者可以通過(智能)指針來存儲組件,派生類型實現爲容器定製的虛擬事件處理程序。還有很多其他的可能性,例如如果您想避免運行時開銷,請考慮CRTP或模板策略類。

2

具有分量保持指向其父被廣泛使用,我不認爲這是不好的做法。它可用於各種各樣的事情,從處理小部件樹到處理丟失或泄露的組件。

要解決的編譯器的問題,你要麼需要把包括行頭衛士裏面,或者有兩個類的前置聲明第三個文件(在適當的命名空間)。

我見過後者在幾大OO庫完成的,它通常然後在項目幾乎所有其他文件包括在內。雖然這會導致名稱空間污染,但它有一些好處(不需要包含完整的類定義或另一個類的依賴關係,只是爲了指向它)。

Widget.hpp:

#include "Library.hpp" 

namespace MyLibrary 
{ 
    class Widget 
    { 
    private: 
     Window * parent; 
    }; 
} 

窗口。HPP:

#include "Library.hpp" 

namespace MyLibrary 
{ 
    class Window 
    { 
    private: 
     std::vector<Widget*> widgets; 
    }; 
} 

Library.hpp:

namespace MyLibrary 
{ 
    class Window; 
    class Widget; 
} 
+0

好的建議。不過,我可能會按照Derek的建議去做,因爲看起來實現起來通常更容易,但仍然可以完成相同的工作。感謝您的意見,但! – Jengerer 2010-11-04 05:07:05

相關問題