【发布时间】:2011-08-08 03:24:27
【问题描述】:
我目前正在使用各种中间件(包括 OGRE(图形)、Bullet(物理)和 OpenAL(声音))在 C++ 中开发游戏引擎,而且我还处于项目初期。正是在这一点上,我正在设置我的错误处理机制。
我计划通过将引擎包含在 DLL 中并导出一个函数来向用户公开该引擎,该函数将返回一个指向主引擎对象的指针。该对象将包含您可以访问引擎的各种组件的方法 - 大多数对象将通过接口访问,因此用户对实际实现是隐藏的。
我倾向于使用错误代码作为我的错误报告机制而不是异常
- 通过 DLL 链接传递异常会增加错误报告的复杂性,迫使我导出异常类等,并且
- 错误代码通常更有效,因此它们在实时游戏引擎中很常见。
唯一出现的问题是构造函数——它们不能返回错误代码。因此,我计划对所有方法使用错误代码,但在构造函数失败时抛出异常。由于我计划使用工厂方法模式来生成对象并将它们传递给用户代码,因此异常将由引擎在内部处理,并且用户只会在构造失败时得到一个空指针。我意识到您通常不应该混合使用异常和返回码,但替代方案听起来也好不到哪里去:
- 您无法在构造函数中执行任何操作并使用某种 init() 方法,但 RAII 出现了。
- 您可以设置一个标志并使用某种 isOk() 或 isInitialized() 方法,但现在您已经介绍了对象存在但未能初始化的某些僵尸状态的可能性,并且您可能忘记检查确保它还活着。
我了解这两种系统的固有成本和收益,并意识到将两者混合通常是个坏主意。但是,既然构造函数不能有某种返回值,那么当构造函数失败并在别处使用错误码时,会不会是不合理的抛出异常呢?谁有更好的建议?
【问题讨论】:
-
为什么要使用 DLL?为什么不是静态库?
-
@unaperson:灵活性、模块化、“推荐性”,它是一个被多个应用程序使用的库,等等……为什么不使用 DLL?
-
@rubenvb 静态库可以做到这一切。 DLL 是对 20 年前不再存在的问题(磁盘空间有限)的解决方案。
-
如果您从不将异常传播到内部工厂代码之外,那么问题出在哪里?您不会将异常与错误代码混为一谈,因为没有人会看到您的异常。
-
@unaperson:不,他们不会:你不能用更新版本替换静态库而不替换链接到它的所有应用程序,你不能为一个实例共享相同的内存静态库(链接到它的每个应用程序都有自己的库副本),对于大型项目:您必须完全重新链接所有代码,而不仅仅是重新链接 DLL。当然,我不必链接到这样的东西:en.wikipedia.org/wiki/Dynamic_link_library#Features_of_DLL。我并不是说 DLL 是最好的,我只是说它们仍然可以解决不同的问题。
标签: c++ design-patterns dll exception-handling error-handling