c++ - 为什么不能使用非成员函数来重载赋值运算符?

标签 c++ operator-overloading assignment-operator

赋值运算符可以使用成员函数重载,但不能使用非成员friend函数:

class Test
{
    int a;
public:
    Test(int x)
        :a(x)
    {}
    friend Test& operator=(Test &obj1, Test &obj2);
};

Test& operator=(Test &obj1, Test &obj2)//Not implemented fully. just for test.
{
    return obj1;
}

它会导致这个错误:

error C2801: 'operator =' must be a non-static member

为什么不能使用 friend 函数来重载赋值运算符?编译器允许使用 friend 重载其他运算符,例如 +=-=。支持 operator= 的内在问题/限制是什么?

最佳答案

首先,需要注意的是,这与具体实现为 friend 的操作符无关。它实际上是将复制分配实现为成员函数或非成员(独立)函数。该独立函数是否会成为 friend 完全无关紧要:它可能是,也可能不是,取决于它想在类中访问什么。

现在,这个问题的答案在 D&E 书 (The Design and Evolution of C++) 中给出。这样做的原因是编译器总是为类声明/定义一个成员复制赋值运算符(如果你不声明自己的成员复制赋值运算符)。

如果语言还允许将复制赋值运算符声明为独立(非成员)函数,您可能会得到以下结果

// Class definition
class SomeClass {
  // No copy-assignment operator declared here
  // so the compiler declares its own implicitly
  ...
};

SomeClass a, b;

void foo() {
  a = b;
  // The code here will use the compiler-declared copy-assignment for `SomeClass`
  // because it doesn't know anything about any other copy-assignment operators
}

// Your standalone assignment operator
SomeClass& operator =(SomeClass& lhs, const SomeClass& rhs);

void bar() {
  a = b;
  // The code here will use your standalone copy-assigment for `SomeClass`
  // and not the compiler-declared one 
}

如上例所示,复制赋值的语义会在翻译单元的中间发生变化——在声明独立运算符之前,使用编译器的版本。声明后使用您的版本。程序的行为将根据您将独立复制赋值运算符的声明放在哪里而改变。

这被认为是 Not Acceptable 危险(确实如此),因此 C++ 不允许将复制赋值运算符声明为独立函数。

确实,在您的特定示例中,恰好使用 friend 函数,该运算符很早就在类定义中声明(因为这是声明 friend 的方式)。因此,在您的情况下,编译器当然会立即知道您的运算符的存在。但是,从 C++ 语言的角度来看,一般问题与友元函数没有任何关系。从 C++ 语言的角度来看,它是关于成员函数与非成员函数的,由于上述原因,完全禁止复制赋值的非成员重载。

关于c++ - 为什么不能使用非成员函数来重载赋值运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3933637/

相关文章:

c++ - 从双秒到 std::chrono::steady_clock::duration 的简洁转换?

c++ - 在 C++ 中嵌入 Lua

c++ - 了解 bool 运算符==(参数1,参数2)

python - 为什么我不能将任意可迭代对象分配给步长为 -1 的扩展切片?

c++ - 重载运算符 = 在 C++ 中有两个参数

c++ - 将指针转换为引用时会发生复制操作吗?

c++ - 在 Qt 5.5 中持续检查主循环

c++ - 派生类使用基类中的重载运算符时出错

c++ - 平等的定义

r - 如何为数据框行子集的列分配值