2013-08-27 141 views
0

我一直在做一些閱讀,一般的看法似乎是,儘可能地避免兩相初始化。我很同意它所說的。但我不覺得它很容易消除。避免兩相初始化

這裏是一個完全由例子,雖然極力基於一些實際的代碼 -

想象我建立一個遊戲。主遊戲類需要構建一個用於3d渲染的「RenderDevice」對象。但爲了構建它,它需要從配置文件加載一些設置。並且要繪製一個Window對象。還有一個記錄器對象和一個內存池。我的代碼現在把所有的這些東西爲類成員在構造函數中做一點,然後調用的初始化函數的每個對象上的相關參數,像: -

// Much simplified code to make a point 
Game::Game() 
{ 
    memoryPool_.init(10000000); // Amount of memory to allocate 
    logger_.init("logfile.txt", memoryPool_); 
    window_.init(2000, 1000); // Make a nice big window 
    renderDevice_.init(window_, logger_, memoryPool_); 
} 

這對我來說似乎工作得相當好。但是這是兩個階段。每個對象只是由它的構造函數部分構造而成。所以我不得不做很多這樣的事情,而不是讓代碼變得「乾淨」。

Game::Game() : 
    memoryPool_(1000000), 
    logger_("logfile.txt", memoryPool_), 
    window_(2000, 1000), 
    renderDevice_(window_, logger_, memoryPool) 
{ 
} 

現在,代碼看起來相當醜陋的我,也是相當脆弱的初始化的順序取決於它們在類,這裏沒有列出的順序聲明的順序上。隨着更多的數據被添加到課堂中,情況會變得更糟。這裏的對象只需要幾個參數,但如果他們需要更多的數據,這將快速失控。

它有每個對象的構造準備做的工作的優勢,但它看起來醜陋的我,似乎相當脆弱,而且容易出錯...

所以我的問題是有我錯過了點?有一個更好的方法嗎?我應該停止擔心,只是做這個,或者我應該使用我的原始代碼?或者,我的整個設計在某種程度上是錯誤的,所以這個問題沒有用?

基本上最好的做法是什麼?

+5

我覺得你很困惑。 – Marcin

+7

最好的做法絕對是無論什麼原因,我不明白,你認爲醜陋和脆弱。事實是,它比兩階段初始化更堅實(也沒有醜陋)。 – syam

+0

@Marcin Hehe我很困惑,這是閱讀太多:)好吧,我猜這不是醜陋的。我會嘗試使用它,看看它是如何工作:) – jcoder

回答

8

現在,代碼看起來相當醜陋的我

不這樣看我。也許你只是不習慣它?

爲初始化的順序取決於它們在類中聲明的順序相當脆弱的,而不是爲了在這裏列出

打開你的編譯器的警告,它會告訴你那些之間的不匹配兩個命令。 (我知道鏘有這個警告,我敢肯定GCC有這一點。不太肯定MSVC)

的對象在這裏只需要幾個參數,但如果他們需要更多的數據,這將迅速得到不可收拾。

當你使用init()時,我看不出有什麼不同。

+0

當我使用init()時,我可以做幾行代碼來計算參數傳遞給一個變量來初始化它,我不能在構造函數參數列表中做到這一點。我想我仍然可以調用函數來獲取值。 – jcoder

+1

是的,功能是去這裏的方式。超過最小值計算也會使基於init的構造函數主體變得混亂。 –

+0

默認情況下,GCC確實有該警告。 – vines

0

根據我的經驗,init函數用於有可能出現錯誤和異常不能使用/拋出的地方。你提到的例子都有錯誤情況,似乎只是拋出一個異常,因爲沒有檢查到返回值。

我認爲從Game中的init函數調用一組inits是一個很好的習慣,而不是從構造函數本身調用inits。

相關問題