首页 > 解决方案 > 如何重载 C++ 运算符,但仅适用于某些输入?

问题描述

我有一个类,我想为它重载加法运算符。a对于我的用例,只有在每个对象的变量相等的情况下才允许添加才有意义。

处理他们不是的情况的最佳方法是什么?抛出异常,还有别的吗?

class A {
private:
    int a, b;

public:
    A(int a, int b)
        :a(a), b(b) {}

    A& operator+=(const A& rhs) {
        if (this->a == rhs.a) {
            this->b += rhs.b;
            return *this;
        }
        else { //this->a != rhs.a
            //what should I put here?
        }
    }
};

.

编辑:

这些对象是在文件 io.io 运行时创建的。

这些对象代表频谱中的一个数据点。只有在两个数据点位于相同位置时,添加它们的强度才有意义。

a限制在范围内 (-180.0, 360.0)

标签: c++operator-overloading

解决方案


这闻起来像是a类型的属性,而不是值的属性......这个类到底代表什么?

解决此问题的最小可行(恕我直言)方法是明确地从“任何事情发生”类型转换为“与 a 的特定值兼容的类型”。IE:

MyClass x(1,2), y(1,5);

x += y; // won't compile

x.makeCompatibleWith(y) += y; // will compile

拥有像+=throw 这样的算术运算符通常是一种悲观。相反,让其他东西假设成本 - 然后成本是明确的,你可以不+=扔。在项目中搜索成本高昂的操作也很容易(嗯,makeCompatibleWith并不是非常昂贵,只是比+=它增加了异常处理的开销更昂贵)。

假设无效情况是为了在测试中被捕获,该makeCompatibleWith函数可以满足assert它需要的条件,但是在发布版本中它会返回一些虚拟对象,+=因为它不会修改,所以它会变成无操作x- 同时仍然保持+=非常简单快捷。

至于究竟应该makeCompatibleWith返回什么:这取决于你。它可以是带有引用的类型,例如:

class MyClass
{
  int a, b;
  struct Internal
  {
    MyClass &val;
    Internal(MyClass &val) : val(val) {}
    MyClass &operator+=(const MyClass &o) noexcept {
      val.b += o.b;
      return val;
    }
    MyClass operator+(const MyClass &o) const noexcept {
      return { val.a, val.b + o.b };
    }
  };
public:
  MyClass() : a{}, b{} {}
  MyClass(int a, int b) : a(a), b(b) {}
  Internal makeCompatibleWith(const MyClass &o) noexcept {
    thread_local static MyClass dummy;
    assert(a == o.a);
    if (a != o.a)
      return { dummy };
    return { *this };
  }
};

请注意,如果不是线程本地的makeCompatibleWith,则从多个线程使用时将是未定义的行为。dummy


推荐阅读