Если вы определяете operator<<
функцию-член, она будет иметь другой разложенный синтаксис, чем если бы вы использовали не-член operator<<
. Не-член operator<<
- это бинарный оператор, а член operator<<
- унарный оператор.
struct MyObj;
std::ostream& operator<<(std::ostream& os, const MyObj& myObj);
struct MyObj
{
MyObj& operator<<(std::ostream& os) { os << *this; return *this; }
int value = 8;
};
std::ostream& operator<<(std::ostream& os, const MyObj& myObj)
{
return os << myObj.value;
}
Итак .... как вы их на самом деле называете? Операторы в некотором роде странные, я предлагаю вам написать operator<<(...)
синтаксис в уме, чтобы все было понятно.
MyObj mo;
mo << std::cout;
mo.operator<<(std::cout);
Или вы можете попытаться вызвать бинарный оператор, не являющийся членом:
MyObj mo;
std::cout << mo;
operator<<(std::cout, mo);
Вы не обязаны заставлять эти операторы вести себя интуитивно, когда вы превращаете их в функции-члены, вы можете определить operator<<(int)
сдвиг влево для некоторой переменной-члена, если хотите, понимая, что люди могут быть немного застигнуты врасплох, независимо от того, сколько комментариев вы можете написать.
Почти наконец, могут быть моменты, когда оба разложения для вызова оператора действительны, у вас могут возникнуть проблемы, и мы отложим этот разговор.
Наконец, обратите внимание, как странно было бы написать унарный оператор-член, который должен выглядеть как бинарный оператор (поскольку вы можете сделать операторы-члены виртуальными ... также пытаясь не переходить и не спускаться по этому пути ... )
struct MyObj
{
std::ostream& operator<<(std::ostream& os) { os << *this; return os; }
int value = 8;
};
Этот синтаксис сейчас будет раздражать многих программистов ....
MyObj mo;
mo << std::cout << "Words words words";
mo.operator<<(std::cout) << "Words words words";
operator<<(mo.operator<<(std::cout), "Words words words");
Обратите внимание, что здесь cout
второй аргумент в цепочке .... странно, правда?