Проблема в том, что ваш operator<<
будет принимать ostream
в качестве второго параметра, а не первого.Таким образом, вы могли бы сделать myObject << std::cout
, но это выглядело бы не интуитивно, и вы не смогли бы связывать вызовы из-за левой ассоциативности operator<<
.
Еще одно преимущество объявления оператора как другаВ отличие от функции-члена, автоматические преобразования могут происходить.Это означает, что если у вас есть класс B
, который не является производным от A
, но имеет конструктор B(A const&)
, вы все равно сможете выполнить std::cout << my_b;
и преобразовать его в A
, а затемнапечатано.
К счастью, определение operator<<
как друга может быть сделано в классе, если вы предпочитаете.Ваш код может быть записан как
class A {
int i;
friend std::ostream& operator<<(std::ostream& o, A const& a) {
o << a.i;
return o;
}
};
Почему стандарт не позволяет вам указывать, на какую сторону должен идти аргумент?Давайте представим, что это так, и добавим ключевые слова left_of
и right_of
, чтобы указать:
struct B;
struct A {
A left_of operator+(B const&) {
return *this;
}
};
struct B {
B right_of operator+(A const&) {
return *this;
}
};
Что происходит сейчас, когда мы делаем A a; B b; f(a + b);
?У каждого класса есть оператор, который обрабатывает этот случай, что означает, что мы не можем решить.В любом случае, видеть, как многие операторы должны дружить из-за возможностей конвертации, не допускать такого рода вещей - не такая уж большая проблема, и предотвращает подобные двусмысленности(Конечно, вы также можете определить оператор-член и свободный оператор, который вызовет очень похожую проблему.)
Кстати, определение вашего friend operator<<
не возвращаетсявсе, что испортит цепочку.