这两种类型的运算符重载有什么区别?

时间:2015-01-06 15:29:57

标签: c++

我一直在查看一些开源代码,我看到了重载运算符的两种不同定义。它们之间有什么区别,这样做有什么好处吗?

例如,我们有一个类的一个例子:

class foo{
public:
    void SetValue(double input_value) {foo_value = input_value};
    double GetValue() {return foo_value;}
private:
    double foo_value;
};

然后我有时会看到两种不同类型/样式的重载加法运算符(例如)

class foo{
    const foo operator+(const foo& input_foo);
};

const foo foo::operator+(const foo& input_foo) {
    foo_value += input_foo.foo_value;
    return *this;
}

我有时会看到的另一种超载类型是:

class foo{
    friend const foo operator+(const foo& input_foo1, const foo& input_foo2);
};

const foo operator+(const foo& input_foo1, const foo& input_foo2); // Defined right after class

const foo operator+(const foo& input_foo1, const foo& input_foo2) {
    foo temp_foo;
    temp_foo.SetValue(input_foo1.GetValue() + input_foo2.GetValue());
    return temp_foo;
}

2 个答案:

答案 0 :(得分:3)

一个重载是成员函数,而另一个是自由函数。

使用自由函数以提供混合模式算术。例如: -

foo f;
2 + f;    __1

__ 1只有在有自由函数operator+时才会编译。在这种情况下,成员函数operator+将不会执行任何操作。

答案 1 :(得分:0)

从外部角度来看,foo::operator+(const foo&)::operaor+(const foo&, const foo&)在置于两个+ - s之间时,使foo符号具有完全相同的作用。特别是第一个就像第二个,当它自己的fisrt参数是*this时。

从内部角度来看,他们可以拥有与foo类不同的功能:::operaor+(const foo&, const foo&)是一个"自由功能" (在全局级别声明的函数):它具有以相同方式处理参数的对称之美,但不能访问foo的私有数据成员,除非foo本身不将其识别为自己的firend

作为成员函数,

foo::operator+(const foo&)可以自由访问所有foo成员和数据,但是 - 作为foo的成员 - 不太适合"泛型算法" (可能更喜欢功能形式)。

关于可能的变体还存在一些其他差异:考虑

foo a;
foo b;
int k;

上面提到的operator+都可以为a+b提供意义,但a+kk+a呢?

对于a+k,您可以有foo::operator+(int)::operator+(const foo&, int),但对于k + a,您需要::operator+(int, const foo&),因为无法+作为int的理解。

所有这一切,你宣言和实施看起来"模糊" (或至少语无伦次):

const foo foo::operator+(const foo& input_foo) {
    foo_value += input_foo.foo_value;
    return *this;
}

当您撰写c = a+b时,您是否希望a的价值发生变化?

你在这里做的是将b添加到a并创建a的副本(为什么const?它毕竟是副本,你已经改变了{ {1}})然后您分配给a

操作员+应创建一个新值,其值为总和

foo foo :: operator +(const foo& rop)const //注意签名,使其与decalration保持一致 {    foo tmp;    tmp.foo_value = foo_value + rop.foo_value;    返回tmp; }

它不是返回类型,而是成员函数本身为c,作为参数(如果通过引用给出),以便确保const a+b a }}或b已更改。返回类型只是一个普通值,您可以让调用者按照自己的意愿处理,因为它返回到自己的堆栈框架中。