2016-07-28 191 views
3

我想在特定實例的構造函數中初始化靜態成員變量。這是一個壞主意嗎?在實例的構造函數中初始化靜態成員

情況如下。我有一個靜態成員變量,這個類的所有實例應該共享。通常,我只是使用靜態初始化器。但是,在構造函數被調用之前,我沒有構造靜態對象所需的必要信息。但是當然,我不想在每次構造函數被調用時創建一個新對象,所以我想要做這樣的事情。

class Foo 
{ 
    static Bar * bar; 
    Foo(Xyz xyz); 
}; 

Bar * Foo::bar = nullptr; 

Foo::Foo(Xyz xyz) 
{ 
    if (Foo::bar == nullptr) 
    { 
     // initialize static bar 
     Foo::bar = new Bar(xyz); 
    } 
} 

我當然知道xyz的migth是不同的調用的Foo構造不同。這對我來說並不重要。

這是不好的軟件設計嗎?我感覺有點奇怪,在構造函數中初始化一個靜態對象。但這與單件設計模式沒有什麼不同。所以也許它沒關係?

編輯

感謝您的意見傢伙。人們似乎並不喜歡這種設計。我將對其進行修改,以便在Foo的第一個實例化之前創建一個Bar,並在Foo的構造函數中將Bar *作爲參數傳遞。每個Foo將有一個指向Bar的指針,我將確保所有Foo都指向相同的Bar。那個更好嗎?

+1

請注意,你不會做初始化。你將會做任務。 – NathanOliver

+0

如何獲得應該用於_initialization_的值?它僅在運行時纔可用嗎?順便說一句,你的樣本不會編譯。 –

+3

單線看起來沒問題。多線程競爭條件。 –

回答

1

這是不好的軟件設計嗎?

一般情況下,它會被認爲是的,是的。有很多原因爲什麼Singleton Pattern或以這種方式具有靜態變量被認爲是不好的設計。


但它不是從Singleton設計模式的不同。所以也許它沒關係?

如果你真的想使之成爲Singleton模式你應該寧願使用Scott Meyer's technique

class Foo 
{ 
    static Bar* bar(Xyz xyz) { 
     static Bar barInstance(xyz); 
     return &barInstance; 
    } 
    Foo(Xyz xyz) : xyz_(xyz) {} 

    void baz() { 
     Bar* b = bar(xyz_); 
     // use b ... 
    } 

private: 
    Xyz xyz_; 
}; 

此代碼將是線程安全的,並且避免了需要檢查是否有nullptr


雖然Bar應該彌補它自己的一個辛格爾頓那麼,你用它在Foo需要的時候:

class Bar { 
public: 
    static Bar& getInstance(Xyz xyz) { 
     static Bar barInstance(xyz); 
     return &barInstance; 
    } 

private: 
    Bar(Xyz xyz) : xyz_(Xyz) {} 
    Bar(const Bar&) delete; 
    Bar(Bar&&) delete; 
    Bar& operator=(const Bar&) delete; 
    Bar& operator=(Bar&) delete; 

    Xyz xyz_; 
}; 

class Foo { 
public: 
    Foo(Xyz xyz) barRef(Bar::getInstance(xyz)) { 
             // ^^^ Notice 1st instance of Foo created 
             //  wins to create the Bar actually 
    } 
private: 
    Bar& barRef; 
}; 
+0

*「但是,我沒有必要的信息來構造靜態對象,直到構造函數被調用」* ... – Jarod42

+1

@ Jarod42這是一個指標,設計是有缺陷的,'酒吧'不應該在一個與'Foo'的靜態關係。我只是想澄清一下_real_ Singleton Pattern的區別。 –

相關問題