c++ - 如何重载 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)
解决方案
这闻起来像是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