Якщо ви визначите 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
тут другий аргумент у ланцюжку .... дивно, правда?