2011-04-18 75 views
1

我目前正在使用包括OGRE(圖形),Bullet(物理)和OpenAL(聲音)在內的各種中間件開發C++遊戲引擎,而且我相當早在項目中。在這一點上,我正在設置我的錯誤處理機制。錯誤處理範例:混合異常和錯誤代碼

我計劃通過將引擎包含在DLL中並將導出的函數返回到主引擎對象的指針來向用戶公開引擎。該對象將包含可以訪問引擎的各種組件的方法 - 大多數對象將通過接口訪問,以便用戶可以從實際實現中隱藏。

我傾向於通過DLL鏈接使用錯誤代碼爲我的錯誤報告機制,而不是例外,因爲

  1. 傳遞異常增加了錯誤報告的複雜性,迫使我出口的異常類,等等。 ,並且
  2. 錯誤代碼通常更高效,因此它們在實時遊戲引擎中很常見。

那麼出現的唯一問題就是帶構造函數的問題 - 它們不能返回錯誤代碼。因此,我計劃對所有方法使用錯誤代碼,但在構造函數失敗時拋出異常。由於我打算使用工廠方法模式來生成對象並將它們傳遞給用戶代碼,異常將由引擎在內部處理,並且用戶在構造失敗時只會獲得空指針。我知道你平時應該不能混合異常和返回代碼,但該方案不健全任何好轉:

  • 在構造函數中你不能做任何事情,使用某種類型的init()方法,但有去RAII。
  • 你可以設置一個標誌,並有一些isOk()或isInitialized()方法,但現在你已經介紹了一些殭屍狀態的可能性,對象存在但未能初始化,你可能忘記檢查確保它還活着。

我意識到兩個系統的內在成本和收益,並認識到混合兩者通常是一個壞主意。然而,由於構造函數不能有某種返回值,當構造函數失敗並在其他地方使用錯誤代碼時,是否會出現不合理的拋出異常?有沒有人有更好的建議?

+0

爲什麼要使用DLL?爲什麼不是靜態庫? – 2011-04-18 19:20:10

+0

@unperson:靈活性,模塊性,「推薦性」,它是一個由多個應用程序使用的庫,等等......爲什麼不使用DLL? – rubenvb 2011-04-18 19:24:53

+0

在構造函數中出現錯誤的Re標誌:好的,錯誤代碼同樣容易被忽略。 – delnan 2011-04-18 19:26:07

回答

1

我個人更喜歡異常(並有很多很好的理由)。但是,將DLL代碼中的異常引發到用戶代碼(反之亦然)是一個不好的主意。所以在你的情況下,我會使用模塊(DLL和可執行文件)中的異常,並使用基於error_return的API來導出DLL。當使用DLL的基於error_return的API時,我會爲這些error_return-ing函數使用基於異常的包裝器。

IMO以任何方式返回錯誤指示符(通過返回值或通過引用或通過每個線程的錯誤代碼)用無盡的錯誤檢查分支havily混淆代碼。我的方式(以及我對C++方式的理解)只有在成功的情況下才會返回。

+0

在DLL中處理異常的絕佳建議。然而,你已經對由錯誤代碼引起的無盡條件檢查做了如此強烈的論述,我認爲我將使引擎成爲一個靜態庫,以便我可以正確使用異常。謝謝您的幫助。 – 2011-04-18 23:15:24

0

就你而言,我會說螺絲RAII並使用Init方法。混合使用兩種範例不僅會降低一致性,還會迫使引擎的消費者在某些人不喜歡的情況下實現異常處理機制。

0

我現在更願意只與例外的工作,但如果你仍然需要或希望使用錯誤代碼與構造,我喜歡的是強制用戶一個形式給出傳遞在構造函數的參數:

class Foo { 
    public: 
     Foo(int &errorCode) { 
      //our init code 
      rc = SOMETHING_BAD; 
     } 
}; 

//on a method or function: 
int errorCode; 
Foo foo(errorCode); 
if(errorCode != RESULT_OK) 
{ 
     //handle it 
} 

我認爲這比使用IsOk()方法或分離的Init方法要好,因爲它至少強制用戶傳遞一個變量作爲參數,並且很難忘記檢查錯誤,缺點是有時候它很無聊爲此僅聲明變量。

我的2美分。