2012-09-13 176 views
2

我以某種方式讀取了在構造函數中做對象創建的不良風格......但是,我忘記了爲什麼它被認爲是不好的風格(特別是在使用依賴注入時)。在構造函數中創建對象

這裏對象創建在構造函數的僞代碼的例子:

Myclass 
{ 
    Myclass(MyMemberFactory& fac) 
    { 
     for(Some criteria) 
      push_back(fac.createMyMemberType()); 
    } 

    vector<MyMemberType*> getMyMember(); 
    { 
     return myMember_; 
    } 
    ... 

private: 
    vector<MyMemberType*> myMember_; 
} 

所以,你可以使用單元測試沒有問題,因爲你可以模擬走MyMemberFactory。 如果我想在一個獨立的初始化方法中移動for-loop,那麼檢查雙重初始化是必要的,並且如果初始化已經完成,所有getter將需要首先進行。這裏的代碼,通過使用一個單獨的初始化:

Myclass 
{ 
    Myclass() : isInitialized_(false) 
    { 

    } 

    void initialize(MyMemberFactory& fac); 
    { 
     if(isInitialized_) 
      throw "Error: Double-Init is not permitted."; 

     for(Some criteria) 
      push_back(fac.createMyMemberType()); 

     isInitialized_ =true; 
    } 

    vector<MyMemberType*> getMyMember(); 
    { 
     if(isInitialized_) 
      throw "Initialize first!"; 

     return myMember_; 
    } 
    ... 

private: 
    vector<MyMemberType*> myMember_; 
    bool isInitialized_; 
} 

所以知道任何理由,我爲什麼要使用第二種方法比第一種方法?或者,也許我只是有錯誤的想法,第一種方法是完全正確的?

回答

2

第一種方法其實很好。這不是構造函數中的對象創建有問題,而是使用構造函數這樣做是有問題的。因此,

Myclass() 
{ 
    MyMemberFactory fac; 
    for(Some criteria) 
     push_back(fac.createMyMemberType()); 
} 

會有問題,因爲客戶端不能再使用不同的工廠(例如測試)。

+0

好的,非常感謝......我只是以一般的方式在腦海中受到了限制。 – Alex

3

如果構造函數拋出異常,析構函數將不會被調用,因此您將失去手動分配的所有內存。

+1

他的第二個變體是一樣的,因爲'isInitialized_'只在'initialize'完成時才設置爲true。第二個版本並不比第一個更好。真正的解決方法是(如果你必須處理異常!)首先不具有原始指針向量。 –

+0

@Frerich,是的,第二個版本不是更好。這只是我能想到的唯一的理由。 – SingerOfTheFall

+0

好點..實際上在真正的代碼中,我使用成員的自動指針..我刪除它們來簡化問題。 – Alex

相關問題