运营商==或!=抛出这种情况?

时间:2012-12-07 00:47:42

标签: c++ exception operator-overloading

我正在编写一个程序,我已经创建了一个POD结构的std :: vector。结构的一个成员是唯一标识符。

为了能够使用std :: binary_search,我必须实现operator<对于结构。遵循指南here,我正在为==,!=,<,>,> =和< =。

编写完整的重载集。

这提出了一个我不确定如何处理的问题。向量将按照我为每个结构分配的唯一ID进行排序。如果两个结构具有相同的标识符,则它们是相同的。但是,如果两个结构具有相同的标识符但其他成员中的数据不同,则可能会出现这种情况。

这绝不会发生。让比较运算符检查其余字段然后抛出异常(如果它们不同但ID是相同的)是否合适?什么样的例外是最合适的?

5 个答案:

答案 0 :(得分:7)

这只是SCombinator's answer.

的扩展

你说“这应该永远不会发生”。意味着您要使用断言,而不是异常(或两者的组合)。一个例外可以隐藏错误 - 好吧,不要隐藏,但你将能够捕获它并继续。它更适合您没有真正计划的特殊情况 - 例如您尝试打开不存在的文件。它不是逻辑的一部分,文件丢失,你的小弟弟意外删除了你的文件,或者认为它是病毒的侵略性反病毒,或者其他什么 - 这只是一种特殊的情况。

如果具有相同ID但不同的成员是永远不会发生的事情,那基本上就是一个断言。它是逻辑的一部分 - 如果你愿意的话,也是要求的一部分。抛出异常只是指出了这一点,但实际上并没有办法从中恢复。当你意识到出现问题时,它已经迟到了。你有两个具有相同id但又不同的对象,你不知道哪个是正确的,你不知道为什么存在不正确的对象,依此类推。你可能甚至不想从中恢复。应用程序已经处于错误状态 - 两个相互矛盾的对象已经存在。您的应用程序处于无法恢复的状态 - 如果继续使用它,您可能会得到错误的结果或更糟。

如果它不是一个关键的断言,你也可以在之后抛出一个异常,并提供一个干净的方式来关闭应用程序,但这只是一个美化。

一般来说,我遵循一个简单的规则 - 如果它是在特殊情况下可能发生的事情,我会使用例外。如果它是永远不会发生的事情,如果它确实存在,意味着代码中的逻辑严重错误,我使用断言(可能是强制崩溃)。

答案 1 :(得分:2)

如果这样的事情是逻辑错误,您应该使用assert

答案 2 :(得分:2)

嗯,你必须问自己一些问题:

1)这是否可能在测试期间发生(即发出错误信号)但在正常执行期间永远不会发生?如果答案是肯定的,请使用assert

2)这是否会在正常运行时发生,如果是,程序是否可以恢复并继续执行?如果答案是肯定的,抛出错误,捕获并处理它。

3)这是否会在正常运行时发生并且无法恢复?如果是,请调用abort或类似的内容(exit, terminate)或抛出您不会处理的异常。

答案 3 :(得分:1)

创建数据时应拒绝错误数据。比较运营商的工作不是排除错误;应该在之前程序执行任何严重的数据操作。所以问题的答案是否定的,operator==operator!=不应该对坏数据抛出异常;它们应该假设传递给它们的数据是有效的。

答案 4 :(得分:0)

您可以使用通过二叉搜索树实现的map,尽管您要复制id。然后,你甚至不需要在结构中存储id,因为它们应该是唯一的。

// Example POD struct.
struct MyStruct
{
  int id; // Redundant.
  char a;     
}

std::map<int, MyStruct> myMap;
MyStruct m; m.id = 1;
myMap[m.id] = m;
// Or simply..
myMap[1] = m;