Во-первых, следует отметить, что это не имеет ничего общего с оператором, реализуемым как друг , в частности. На самом деле речь идет о реализации копирования-назначения как функции-члена или как не-членской (автономной) функции. Будет ли эта автономная функция другом или нет, совершенно не имеет значения: это может быть, а может и не быть, в зависимости от того, к чему она хочет получить доступ в классе.
Теперь ответ на этот вопрос дан в книге D & E ( Дизайн и эволюция 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
}
Как видно из приведенного выше примера, семантика копирования-присваивания будет меняться в середине блока перевода - до объявления вашего автономного оператора используется версия компилятора. После объявления ваша версия используется. Поведение программы будет меняться в зависимости от того, куда вы поместили объявление вашего автономного оператора копирования-присвоения.
Это было сочтено неприемлемо опасным (и это так), поэтому C ++ не позволяет объявлять оператор копирования-копирования как отдельную функцию.
Это правда, что в вашем конкретном примере, который, в частности, использует функцию friend , оператор объявляется очень рано, внутри определения класса (так как именно так объявляются друзья). Итак, в вашем случае компилятор, конечно же, сразу узнает о существовании вашего оператора. Однако с точки зрения языка C ++ общая проблема никак не связана с дружественными функциями. С точки зрения языка C ++ речь идет о функциях-членах, а не о функциях-членах, а перегрузка копирования-присваивания, не связанная с членами, просто полностью запрещена по причинам, описанным выше.