【问题标题】:How do I indicate that a class doesn't support certain operators?如何指示一个类不支持某些运算符?
【发布时间】:2012-06-11 23:04:54
【问题描述】:

我正在编写一个表示序数刻度的类,但没有逻辑零点(例如时间)。 这个比例应该允许加法和减法(operator+operator+=,...),但不允许乘法。

然而,我一直认为这是一种很好的做法,即当重载某个组的一个运算符(在本例中为数学运算符)时,还应该重载属于该组的所有其他运算符。在这种情况下,这意味着我还需要重载乘法和除法运算符,因为如果用户可以使用A+B,他可能希望能够使用其他运算符。

有没有一种方法可以在编译时为此引发错误?最简单的方法是不重载运算符operator*,......但添加比operator* is not know for class "time" 更多的解释似乎是合适的。

或者这是我真的不应该关心的事情(RTFM 用户)?

【问题讨论】:

  • 我已经使用 +std::strings 很长时间了,但从来没有 - 甚至没有一次 - 我期望与他们一起使用 *-...
  • @John Dibling:Ruby 中的"a" * "b""a" - "b" 是什么?
  • 语法错误。但"a" * 5 不是。
  • @John Dibling:Ruby 中的"a" + 5 是什么? C++ 中的 std::string("a") + 5 呢? ...明白我的意思吗?
  • 我认为将加法和乘法分组是没有意义的。甚至没有加减法。有意义的是,如果您提供operatorX,您还应该提供operatorX=(如果它可以比前者更有效),另外,如果您提供==,您应该提供!=(根据前者),operator< 有时可以与operator> 匹配,有时甚至可以与operator<= 匹配,但这取决于域...通常答案是您应该重载那些在 领域的问题。

标签: c++ error-handling compiler-errors operator-overloading


【解决方案1】:

实现一个运算符只是为了发出未实现的信号似乎是做作的。如果有的话,您可以将其定义为 private 成员函数并在其中放置一个 static_assert,如果有人(可能是朋友)尝试使用它,则会显示编译器错误。

算子未实现时的最佳解决方案:不实现它。

【讨论】:

    【解决方案2】:

    编辑: 我注意到你希望它在被使用时被调用,那么最好不要实现它,或者使用 assert 命令来解决运行时错误。

    assert("Message");
    

    【讨论】:

    • 包含header时会显示错误,而不是使用运算符时。
    • 没错,我只是假设当我看到编译时错误时,现在编辑我的答案。
    【解决方案3】:

    只声明重载的操作符,但不要实现它。在编译时,链接器会大惊小怪。

    【讨论】:

    • 或者,你知道,不要声明它。然后编译器会大惊小怪地告诉你哪里出错了。
    • @MagnusHoff - 如果您不声明它,编译器可以尝试隐式进行转换以找到可行的方法。
    【解决方案4】:

    然而,我一直觉得当一个人超载时这是一种很好的做法 某个组的一个运算符(在这种情况下是数学运算符),一个 还应该重载属于该组的所有其他人。

    错了。唯一的组是 ++=- 然后 也许 --=。 “算术运算符”一般不是一个组。考虑类似std::string

    【讨论】:

    • 公平地说,从概念的角度来看,在字符串上使用+ 有点傻。串联 D 样式更有意义。
    • 算术运算符一个组。只是不适用于非算术数据。
    【解决方案5】:

    简短版:有些数学结构有加法但没有乘法,所以不用担心。重载对您所表示的数学结构有意义的运算符。如果有人试图将两次相乘,那么错误no match for operator* in ... 对任何 C++ 程序员都应该是有意义的。如果您认为他们会真正感到困惑,为什么他们不能乘以两次,您可以在文档中进行扩展。我认为编译器的工作并不是真正了解为什么运算符对给定的类没有意义,并在错误消息中表达出来。

    长版:粗略地说,具有“算术运算符”+- 的集合的数学术语是一个(通常你不会使用符号 @ 987654324@ 用于组运算符,除非该运算符是可交换的,因此是 阿贝尔群)。具有乘法但没有加法的集合也可以是一个组,前提是您将 0 排除在集合之外。加法和乘法在结构上是相似的——重要的区别是乘法通常允许至少一个没有逆元的元素 (0),而加法通常不允许。

    + 有时也用作符号,例如自然数中的加法、序列连接,甚至是集合并集,其中元素通常没有逆。在那种情况下,你甚至没有一个组,只有一个二进制函数,你不会定义一元 -,你也可能不会定义二进制 -。在这种情况下,可以说+ 是一个糟糕的运营商选择,但保存std::string 为时已晚。

    如果你的+-组也有*,并且满足+*之间关系的某些条件,那么它是一个,或者字段,如果除加法恒等式之外的每个元素都具有乘法逆元(因此它具有良好的 /)。

    关于时间,考虑两个不同的概念通​​常很有用:绝对时间和持续时间。您可以将两个持续时间相加(给出一个持续时间),或者一个绝对时间和一个持续时间(给出一个绝对时间),但是两个绝对时间相加是没有意义的(什么是“上周一加下周四”?)。

    这种行为类似于在指针(代替绝对时间)和整数(代替持续时间)上定义的运算符,这并非完全巧合。你可以做(char*)0 + 0,但你不能做(char*)0 + (char*)0。所以绝对时间没有加法operator+(abstime, abstime),但可以有operator+(abstime, duration)

    持续时间就像数字,但它们具有物理维度。将持续时间乘以无量纲数 (2.4 * 3s == 7.2s) 是有意义的,但很少将两个持续时间相乘,并且当您这样做时,结果不是持续时间,因为它的单位是秒平方。

    【讨论】:

      猜你喜欢
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 2010-12-07
      • 1970-01-01
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多