2010-01-05 65 views
1

所以我使用組合來彙集對象的集合,所有這些對象都是從基類派生的,可以說組件。 E.g:設計替代?組成和構造

class Component { 
public: 
    Component(); 
    ... 
private: 
    int m_address; 
    ... 
}; 

class SpecializedComponent: public Component { 
public: 
    SpecializedComponent() 
    ... //and so on 
}; 

class SpecializedComponent2: public Component { 
public: 
    SpecialIzedComponent2() 
    ... //and so on 
}; 

class ComponentHolder{ 
    SpecializedComponent* m_descriptiveName; 
    SpecializedComponent2* m_descriptiveName2; 
    // and so on... many different types of components 
} 

因此,每個SpecializedComponentX將通過網絡進行通信與個人數據源,每一個都有自己獨特的地址。這些地址在參數文件中指定。目前,我正在解析參數文件,m_address在派生類構造函數中初始化 - 這是因爲每個m_address都是由我們正在初始化的對象類型指定的。

每個SpecializedComponentX都有一些我想在基類Component中執行的常用功能。所以,我啓動了一個與基類Component相關的線程,對吧?當然 - 有道理。直到我意識到我還沒有該組件的目標地址 - 因爲該對象尚未完全構建。我想旋轉ctor中的基類線程,但我還不知道m_address

我想到解決這個問題的唯一方法是提供一個(簡單的)虛擬函數void start(),派生類可以調用一旦對象完全構造就旋轉起來的線程。這是一個有效的適當的設計選擇還是有一種模式,我可以忽略?謝謝。

回答

0

組件可以有一個構造函數,它具有一個用於初始化m_address的參數。

+0

是的,當然。有時候顯而易見的事情是正確的。 – jdt141 2010-01-05 16:36:24

0

如果這個通用的功能以任何方式依賴於SpecializedComponent,SpecializedComponent2的狀態,或者這是一個SpecializedComponent或SpecializedComponent2的事實,那麼你不能在Component的構造函數中真正做到這一點,除非你傳入參數到它。將類型標識符傳遞給Component構造函數以在那裏進行這種初始化有時是一種必要的邪惡。

但是,在這種情況下,您可以創建派生類可以調用的虛函數。但是,假設您將此虛函數調用放置在SpecializedComponent構造函數中。如果你以後從這個(SuperSpecializedComponent)派生出另一個類並且使用這個虛函數,那麼你從SpecialzedComponent構造函數調用的調用甚至不會觸發這個函數。道德:不要從構造函數調用虛函數。

我認爲最簡潔的方法是建立一個2階段結構。一個構造函數,用於完成對象的基本連接以及在使用它之前必須調用的Init()方法。客戶端代碼(ComponentHolder?)可以在所有對象完全構建後調用此Init。

0

爲什麼start()方法需要是虛擬的?

你可以把非虛擬和實現派生的構造函數 這樣的:

SpecializedComponent::SpecializedComponent() { 
    m_address = getAddressFromParameterFile("SpecializedComponent"); 
    start(); 
} 

這是最好的對象後,調用start()是完全 構造,因爲兩步施工誤差易發。 (如果你 需要兩個步驟的建設,考慮工廠(或工廠方法),以 確保只有完全構造的對象存在。讓構造 私營和工廠(方法)的朋友。)

另一種方式是將地址的計算移出 對象構造。這將導致這樣的代碼:

SpecializedComponent::SpecializedComponent(const std::string& address) 
: Component(address) 
{} 

Component::Component(const std::string& address) 
: m_address(address) 
{ 
    start(); 
} 

這種方法增加了衍生 SpecializedComponents的可測試性,因爲它消除對 參數文件的依賴。

爲了方便,你可以到實例提供靜態工廠方法 您SpecializedComponents:

SpecializedComponent* SpecializedComponent::create() { 
    std::string address = getAddressFromParameterFile("SpecializedComponent"); 
    return new SpecializedComponent(address); 
} 

BTW:考慮持有,而不是原始指針的shared_ptr在ComponentHolder。