我正在学习C ++,我想知道是否可以深入了解创建二元运算符的首选方法,这些运算符可以处理两种不同类型的实例。这是我用来说明我的担忧的一个例子:
class A;
class B;
class A
{
private:
int x;
public:
A(int x);
int getX() const;
int operator + (const B& b);
};
class B
{
private:
int x;
public:
B(int x);
int getX() const;
int operator + (const A& A);
};
A::A(int x) : x(x) {}
int A::getX() const { return x; }
// Method 1
int A::operator + (const B& b) { return getX() + b.getX(); }
B::B(int x) : x(x) {}
int B::getX() const { return x; }
// Method 1
int B::operator + (const A& a) { return getX() + a.getX(); }
// Method 2
int operator + (const A& a, const B& b) { return a.getX() + b.getX(); }
int operator + (const B& b, const A& a) { return a.getX() + b.getX(); }
#include <iostream>
using namespace std;
int main()
{
A a(2);
B b(2);
cout << a + b << endl;
return 0;
};
如果我希望两种类型之间具有对称性,那么哪种方法是上述代码中的最佳方法。选择一种方法比另一种方法有任何可能的危险吗?这是否随退货类型而变化?请解释!谢谢!
答案 0 :(得分:8)
最好的方法是定义(在任一类之外)int operator+ (const A& a, const B& b)
,并在需要时将其作为两个类的友元函数。另外,定义
int operator+(const B& b, const A& a) {return a + b;}
使其对称。
答案 1 :(得分:3)
这种方法的最大风险在于人们倾向于将+视为对称算子。这是写的方式,它不是(除非你的实现相同)。
至少应该将+作为外部二元运算符(不作为成员)重载,然后多次重载它。
但是,你必须要小心,以确保没有任何东西变得模棱两可。你能解释一下你想做什么吗?我不能想到许多不同类型的情况,其中有对称的异质算子是有意义的。
答案 2 :(得分:1)
方法2的主要参数是在两个操作数上进行隐式类型转换,而不仅仅是第二个操作数。这可能会在某个地方避免混淆。
说到这一点,您的示例代码通过两个类上的1-arg构造函数定义从int到A以及从int到B的隐式转换。这可能会导致以后模棱两可。但是如果你为了简洁而省略了“明确”,那就足够了。
我同意Uri的警告:如果你发现自己这样做,你可能正在编写一个其他人会感到困惑的API。为什么A加上B是一个int?是否真的让用户更容易添加a和b,而不是自己调用getX并添加结果?
是不是因为用户非常清楚A和B是整数的包装?如果是这样,那么另一种选择是通过operator int()公开从A到int和B到int的转换。然后a + b将返回一个int是出于明智的原因,你也会得到所有其他算术运算符:
#include <iostream>
struct A {
int x;
explicit A(int _x) : x(_x) {}
operator int() {
return x;
}
};
struct B {
int x;
explicit B(int _x) : x(_x) {}
operator int() {
return x;
}
};
int main() {
A a(2);
B b(2);
std::cout << a + b << "\n";
std::cout << a - b << "\n";
}
答案 3 :(得分:1)
我在评论中读到您的预期用途是添加向量和矩阵。也许您应该考虑仅使用向量是一维矩阵的矩阵。然后你只剩下一种类型和一组运算符:
matrix operator*( matrix const& a, matrix const& b );
matrix operator+( matrix const& a, matrix const& b ); // and so on
如果你想保留矢量类,那么你应该考虑是否还需要一个转置矢量(可能转置只是矢量的内部属性)。
这组操作并不是真正对称的:
vector * matrix = vector matrix * vector_t = vector_t matrix * matrix = matrix vector_t * vector = matrix vector * vector_t = int
你应该提供这三个操作(假设转置是向量的属性):
vector operator*( vector const& v, matrix const& m );
vector operator*( matrix const& m, vector const& v );
matrix operator*( matrix const& m1, matrix const& m2 );
matrix operator*( vector const& v1, vector const& v2 ); // possibly 1x1 matrix, you cannot overload changing only return value
如果可能,全部作为免费功能。即使上面的集合不对称,现实世界也不是,你的用户也会期待它。