为什么在C++中重载运算符时不需要使用作用域解析运算符(::)?

3

通常情况下,当你在类声明中声明一个方法,并在外部定义它时,你需要指定它的作用域。

由于我已经读到运算符基本上是普通方法,我很难理解以下行为:

class A
{
public:
    A(int x)
    { this->x = x;}
    int foo();
    friend const A operator+ (const A& left,const int right);

private:
    int x;
};

const A operator+ (const A& left,const int right) //can't be A::operator+
{
    return A(left.x + right);
}

int A::foo()  // A:: is needed here
{
    return 5;
}

int main(int argc, char **argv) {
    A a(1);
    a = a + 4;
    a.operator =(a+5);
    a.foo();
}

为什么我们不需要指定要定义/重载哪个 "operator+"?操作数是否可以推断出来?

“它是从操作数推断出来的吗?” 是的(简化)。运算符像普通函数或成员函数一样定义,但它们的查找方式比普通函数/成员函数更加棘手和复杂。 - dyp
相关:https://dev59.com/1m445IYBdhLWcg3w_O8m 和 https://dev59.com/BWIk5IYBdhLWcg3wl_TE - dyp
@dyp 注意,该问题涉及到命名空间。当我看到标题时,我也在想“Koenig查找”,但似乎这并不是问题的关键。 - sepp2k
@sepp2k 全局命名空间与 class A 相关联。然而,这个运算符也可以通过未限定的查找找到。我在评论中提到的不是 ADL,而是一般情况下的运算符名称查找。 - dyp
3个回答

10

由于operator+是一个自由函数,它与A类完全无关。它只是恰好有一个参数是A类的实例。

这意味着它不同于A::operator+,后者定义为:

class A {
public:
    const A operator+(const int);
};

在您的代码示例中,您正在为该类定义一个friend函数。因此,自由函数现在可以访问类的私有和受保护部分。如果您不定义它(operator+),friend只能访问A的公共成员。这就是为什么你要将它定义为friend的原因。


1
这是因为在这种情况下,operator+不是A类的成员函数,而是友元函数。

0
在你的情况下,operator+ 不是类A的成员。这通常是定义二元运算符的正确方式,以便该运算符可用于左操作数为字面值的情况。
然而,大多数运算符是在类作用域内定义为普通的类成员。例如,
A& A::operator=(A rhs)
{
    swap(rhs);
    return *this;
}

这是一个更完整的答案:运算符重载


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接