2015-01-02 174 views
2

我有一堆靜態的init()方法,需要在應用程序啓動時調用。有點像不得不做:啓動時自動初始化庫(IES)

A::init(); 
S::init(); 
//... 

一做的事情是這樣的初始化這樣一個靜態變量:

static bool const b{A::init(), S::init(), false}; 

是否有任何更好的替代品存在嗎?

+0

您是否有類似(對稱)的操作在應用程序關閉時執行? –

+0

@MatthieuM。不,我摧毀了一切,需要在破壞者和刪除者中銷燬。 – user1095108

回答

3

您可以使用啓動類的實例初始化其構造函數中的各個組件,並在析構函數中終止它們。例如:

struct Startup 
{ 
    Startup() 
    { 
     A::Init(); 
     B::Init(); 
    } 
    ~Startup() 
    { 
     B::Term(); 
     A::Term(); 
    } 
}; 

namespace { Startup startup; } 

int main() 
{ 
    // do stuff being completely oblivious to the startup 
} 
1

你可以有一個init_dispatch模板,通過一個可變參數的參數列表調用init()

template<typename T> 
struct dispatch 
{ 
    dispatch() { T::init(); } 
}; 

template<typename... Ts> 
struct init_dispatch : std::false_type 
        , dispatch<Ts>... 
{ 
    init_dispatch() : dispatch<Ts>{}... {} 
}; 

static bool const b = init_dispatch<A, S>{}.value; 

Demo

+0

如果'b'永遠不使用ODR,這是否仍然有效? – ildjarn

+0

@ildjarn我不知道我理解這個問題。你對使用'b'有什麼顧慮? – 0x499602D2

+0

如果'b'永遠不使用ODR,那麼爲什麼鏈接器不會優化它,因此'init_dispatch <>'的實例化? – ildjarn

3

我有玩過 「人生前主要」 一在意識到它通常比必要更痛苦之前的次數。

我的建議,因此:

int main() { 
    A::init(); 
    S::init(); 

    // ... 
} 

爲了清楚起見,它可能是值得創建init功能,將調用一切又將這些。

,除非各庫之間的依賴關係樹是晶瑩剔透的,我因爲在鑽石依賴的情況下,建議包裝(即具有B::init通話A::init),你可能最終與基礎庫init被稱爲多倍。

+0

菱形的東西是真的,但一個健壯的'init()'可以處理多個調用就好了。 – user1095108

3

不要自動初始化。在main的啓動過程中明確地初始化您的子系統。

的原因是:

  1. 您可以控制初始化順序
  2. 如果初始化失敗,你可以處理得當
  3. 如果初始化會導致系統崩潰,你將有一個更輕鬆地調試,並希望有適當的堆棧跟蹤
  4. 它確保您完全瞭解初始化過程
1

個人而言,我絕對建議保持簡單:在main之內初始化內容,而不是使用魔術靜態。這樣它明確表示它發生了,並且當發生時它是明確的。你可以在應用程序發生之前和之後推斷應用程序的狀態。

main之前和之後發生的任何事情往往只會導致麻煩。