具有不同类型的C ++对称二元运算符

时间:2009-03-31 19:22:32

标签: c++ operator-overloading symmetric

我正在学习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;
};

如果我希望两种类型之间具有对称性,那么哪种方法是上述代码中的最佳方法。选择一种方法比另一种方法有任何可能的危险吗?这是否随退货类型而变化?请解释!谢谢!

4 个答案:

答案 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

如果可能,全部作为免费功能。即使上面的集合不对称,现实世界也不是,你的用户也会期待它。