在我的最后两个项目中,我看到了一个奇怪的准则,“所有方法/函数都应该使用一些常见的ERROR_CODE类型返回错误代码”。在两个项目中,ERROR_CODE都是一个int typedef。
在C ++中使用它有什么好的理由吗?一些MISRA要求或类似的东西?
我只能看到缺点:
如果函数应返回一个值,则由参数引用完成。 e.g:
string s; ERROR_CODE err = getString(s);
功能的重要性并不明显。一切看起来都一样。错误列表包含从低级别错误到某些特定于域的错误的数百个错误。
您是否体验过这种编程风格?对它或它有好的论据吗?
答案 0 :(得分:3)
我认为这种风格很糟糕有几个原因。
我的观点是,任何具有可管理的失败方式的功能/方法都要么过于复杂,要么考虑不周,可能两者兼而有之。
如果你真的想要返回错误代码,我会交换周围的东西并将指针传递给错误代码作为函数的参数,并使实际结果成为返回值。然后我会选择这两种方法之一来实现错误代码:
int
和一些通用错误类。如果您使用C ++,更好的方法可能是使用异常......
答案 1 :(得分:1)
我见过它。
内核编程就是这样,除非只有一个错误可能。
这听起来不是一个好主意,但也不是那么糟糕。
答案 2 :(得分:1)
团队一致同意返回错误的常用方法并不罕见,因为这有助于为项目代码创建一个共同的“外观和感觉”,就像任何其他团队范围的编码约定一样。这可以帮助新团队成员更快地了解整体情况,并使其他人的代码团队内的维护更加直观。
令我惊讶的是,C ++项目正在统一错误而不是异常。讨论了使用异常与错误代码here的优缺点。
我想有一个支持错误代码处理的论据是,如果你使用C风格的API引导你进入这种方法(咳嗽...... Win32 ......咳嗽)。
答案 3 :(得分:1)
这个习惯用法非常普遍,特别是在C世界。
即使我自己不使用它,我认为它弊大于利(在其他答案中更多),我确实发现了它的优势:一致的方式向呼叫站点报告意外错误。类似于errno变量,但更容易使用。
例如,考虑一组函数:
int a();
std::string b();
double c();
std::list<long> d();
上述每个函数都会以不同的方式指示失败:a()可以返回-1,b()返回空字符串,c()a 0.0和d()返回空列表。这是不一致的,不太直观。现在想象一个函数,其范围涵盖它返回的类型的整个可能范围。那更糟糕。
有些API也可以:
int x(bool* ok);
但是这也会通过一个额外的论点来污染每个函数。
在C中,不幸的是,如果你真的需要设计一个可以指示不同类型故障的API,那么很可能没有太多可能。但是,在C ++世界中,您只能使用异常。
答案 4 :(得分:1)
我已经看到了这样的论点:当链接到由另一个编译器编译的C ++库而不是用于编译二进制文件时,异常可能不起作用。虽然这种不起作用可能完全是真的,但实际上,即使连接过程也不起作用(尽管每个人都可能坚持标准),所以理论上,这个论点是无效的。然而,在实践中,可能(我在这里没有经验,对不起),很少出现名称错误冲突,很少出现对齐冲突,并且,所有其他实现特定的东西都得到广泛认同除了例外情况。
我见过的第二个论点是运行时性能。虽然在异常的情况下堆栈展开是非常昂贵的,但我还没有看到将异常与实际返回代码检查进行比较的公平基准。
在我的典型C ++中,我使用混音。我使用较慢的异常,我真的不希望经常发生的事情或者被测量很少执行的代码路径,但返回更容易破坏并且可能经常调用的东西的代码。 在紧密循环中抛出异常,因为在每次迭代中都有一些有趣的条件成立并不便宜(假设循环体处理它)。