- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我正在使用 VS 2010 在 Windows 上编写 C++ API,它从 DLL 导出多个类。我们计划稍后支持其他平台(MacOS、Linux)。
我目前正在考虑如何设计错误处理。由于跨 DLL 边界的问题(至少在 Windows 中),我不想使用异常。
到目前为止,我想出了以下三个设计。
设计 1:
对于每个方法,返回值将通过分别返回 true/false
或 pointer/nullptr
来指示操作是成功还是失败。然后,客户端可能会调用 GetLastError()
来检索详细说明上次失败的错误代码(枚举)。
typedef std::shared_ptr<Object> ObjectPtr;
class APIClass
{
bool SetSomething(int i);
bool IsSomethingSet();
bool DoSomething();
ObjectPtr GetSomething();
ErrorCode GetLastError();
}
设计 2:
每个方法都返回一个错误代码。 [out] 参数应作为指针传递,[in] 参数应按值或 (const) 引用传递。
typedef std::shared_ptr<Object> ObjectPtr;
class APIClass
{
ErrorCode SetSomething(int i);
ErrorCode IsSomethingSet(bool* outAsk);
ErrorCode DoSomething();
ErrorCode GetSomething(ObjectPtr* outObj);
}
设计 3:
与设计 1 类似,但您可以将可选错误代码作为 [out] 参数传递给每个函数。
typedef std::shared_ptr<Object> ObjectPtr;
class APIClass
{
bool SetSomething(int i, ErrorCode* err = nullptr);
bool IsSomethingSet(ErrorCode* err = nullptr);
bool DoSomething(ErrorCode* err = nullptr);
ObjectPtr GetSomething(ErrorCode* err = nullptr);
}
我想让设计保持简单、一致和干净。作为客户,您更喜欢哪种设计?对于更好的设计,您还有其他建议吗?你能给出一些理由说明为什么一种设计更好,或者这只是一个品味问题?
注意:这里有一个类似的问题:C++ API design and error handling .但我不想在接受的答案中使用解决方案,也不想使用 boost::tuple 之类的东西作为返回值。
最佳答案
好的,所以无异常(exception)约束使成为问题......我不会质疑。
总而言之,这最好取决于您的 API 的具体情况:您倾向于返回的值是否具有备用标记值,您是否想强制/鼓励开发人员更明确地准备和处理错误代码,或者拥有它更可选、隐含和/或简洁。您可能还会考虑您已经在使用的其他库的做法,特别是如果调用者对于给定函数来自哪个库不是很明显的话。因为没有一个最好的万能答案,所以这个问题在 C 世界中存活了几十年(C++ 也有异常(exception))。
几个讨论点...
Sentinel 值(根据您在设计 1 中的指针)在调用者预期它们时工作得很好(例如,程序员倾向于问自己“我可以得到一个空指针吗?这意味着什么?”),直观,一致的,最好是如果它们可以隐式转换为 bool 值,那么它们会在成功时产生真值!这读起来要好得多,尽管显然许多 OS 和标准 C 库函数在失败时返回 -1,因为 0 在有意义的结果集中通常是有效的。
您已经隐含理解的另一个考虑因素:通过依赖函数调用之外的状态,您会引入线程和异步(信号处理)安全问题。您可以记录开发人员不应该限制他们对线程/异步代码的对象的使用,或者为错误代码提供线程特定的存储,但这是一个额外的痛苦维度。返回或传入 ErrorCode 对象可以避免该问题。传入 ErrorCode 对象对调用者来说是一个持续的小负担,但确实鼓励他们明确地考虑错误处理。
关于c++ - C++ API 的错误处理设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9323907/
我已经使用 vue-cli 两个星期了,直到今天一切正常。我在本地建立这个项目。 https://drive.google.com/open?id=0BwGw1zyyKjW7S3RYWXRaX24tQ
您好,我正在尝试使用 python 库 pytesseract 从图像中提取文本。请找到代码: from PIL import Image from pytesseract import image_
我的错误 /usr/bin/ld: errno: TLS definition in /lib/libc.so.6 section .tbss mismatches non-TLS reference
我已经训练了一个模型,我正在尝试使用 predict函数但它返回以下错误。 Error in contrasts<-(*tmp*, value = contr.funs[1 + isOF[nn]])
根据Microsoft DataConnectors的信息我想通过 this ODBC driver 创建一个从 PowerBi 到 PostgreSQL 的连接器使用直接查询。我重用了 Micros
我已经为 SoundManagement 创建了一个包,其中有一个扩展 MediaPlayer 的类。我希望全局控制这个变量。这是我的代码: package soundmanagement; impo
我在Heroku上部署了一个应用程序。我正在使用免费服务。 我经常收到以下错误消息。 PG::Error: ERROR: out of memory 如果刷新浏览器,就可以了。但是随后,它又随机发生
我正在运行 LAMP 服务器,这个 .htaccess 给我一个 500 错误。其作用是过滤关键字并重定向到相应的域名。 Options +FollowSymLinks RewriteEngine
我有两个驱动器 A 和 B。使用 python 脚本,我在“A”驱动器中创建一些文件,并运行 powerscript,该脚本以 1 秒的间隔将驱动器 A 中的所有文件复制到驱动器 B。 我在 powe
下面的函数一直返回这个错误信息。我认为可能是 double_precision 字段类型导致了这种情况,我尝试使用 CAST,但要么不是这样,要么我没有做对...帮助? 这是错误: ERROR: i
这个问题已经有答案了: Syntax error due to using a reserved word as a table or column name in MySQL (1 个回答) 已关闭
我的数据库有这个小问题。 我创建了一个表“articoli”,其中包含商品的品牌、型号和价格。 每篇文章都由一个 id (ID_ARTICOLO)` 定义,它是一个自动递增字段。 好吧,现在当我尝试插
我是新来的。我目前正在 DeVry 在线学习中级 C++ 编程。我们正在使用 C++ Primer Plus 这本书,到目前为止我一直做得很好。我的老师最近向我们扔了一个曲线球。我目前的任务是这样的:
这个问题在这里已经有了答案: What is an undefined reference/unresolved external symbol error and how do I fix it?
我的网站中有一段代码有问题;此错误仅发生在 Internet Explorer 7 中。 我没有在这里发布我所有的 HTML/CSS 标记,而是发布了网站的一个版本 here . 如您所见,我在列中有
如果尝试在 USB 设备上构建 node.js 应用程序时在我的树莓派上使用 npm 时遇到一些问题。 package.json 看起来像这样: { "name" : "node-todo",
在 Python 中,您有 None单例,在某些情况下表现得很奇怪: >>> a = None >>> type(a) >>> isinstance(a,None) Traceback (most
这是我的 build.gradle (Module:app) 文件: apply plugin: 'com.android.application' android { compileSdkV
我是 android 的新手,我的项目刚才编译和运行正常,但在我尝试实现抽屉导航后,它给了我这个错误 FAILURE: Build failed with an exception. What wen
谁能解释一下?我想我正在做一些非常愚蠢的事情,并且急切地等待着启蒙。 我得到这个输出: phpversion() == 7.2.25-1+0~20191128.32+debian8~1.gbp108
我是一名优秀的程序员,十分优秀!