2011-04-18 90 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美分。