Это в основном вопрос, есть ли «правильный» способ реализации operator<<
? Читая это, я вижу что-то вроде:
friend bool operator<<(obj const& lhs, obj const& rhs);
предпочтительнее чем-то вроде
ostream& operator<<(obj const& rhs);
Но я не совсем понимаю, почему я должен использовать тот или другой.
Мой личный случай:
friend ostream & operator<<(ostream &os, const Paragraph& p) {
return os << p.to_str();
}
Но я, наверное, мог бы:
ostream & operator<<(ostream &os) {
return os << paragraph;
}
На каком основании я должен принять это решение?
Примечание :
Paragraph::to_str = (return paragraph)
где абзац - это строка.
c++
operator-overloading
Федерико Булес
источник
источник
Ответы:
Проблема здесь в вашей интерпретации статьи, на которую вы ссылаетесь. .
равенство
Эта статья о человеке, у которого возникли проблемы с правильным определением операторов отношений типа bool.
Оператор:
Эти операторы должны возвращать логическое значение, поскольку они сравнивают два объекта одного типа. Обычно эти операторы проще всего определить как часть класса. Это связано с тем, что класс автоматически является другом самого себя, поэтому объекты типа Paragraph могут проверять друг друга (даже частные члены друг друга).
Существует аргумент в пользу создания этих автономных функций, поскольку это позволяет автоматическому преобразованию преобразовывать обе стороны, если они не одного типа, в то время как функции-члены позволяют автоматически преобразовывать только правая часть. Я считаю, что это аргумент бумажного человека, поскольку вы действительно не хотите, чтобы автоматическое преобразование происходило в первую очередь (обычно). Но если это то, что вам нужно (я не рекомендую), то размещение компараторов отдельно может быть выгодным.
Потоковый
Операторы потока:
Когда вы используете их как операторы потока (а не двоичный сдвиг), первым параметром является поток. Поскольку у вас нет доступа к объекту потока (его нельзя изменять), они не могут быть операторами-членами, они должны быть внешними по отношению к классу. Таким образом, они должны либо быть друзьями класса, либо иметь доступ к общедоступному методу, который будет выполнять потоковую передачу за вас.
Эти объекты также традиционно возвращают ссылку на объект потока, чтобы вы могли связать операции потока вместе.
источник
operator<<
private:
?freiend
это способ расширить общедоступный интерфейс без нарушения инкапсуляции. Прочтите programmers.stackexchange.com/a/99595/12917Вы не можете сделать это как функцию-член, потому что неявный
this
параметр - это левая часть<<
оператора -оператора. (Следовательно, вам нужно будет добавить его как функцию-член кostream
классу. Не очень хорошо :)Могли бы вы сделать это как бесплатную функцию без
friend
этого? Это то, что я предпочитаю, потому что это дает понять, что это интеграцияostream
, а не основная функциональность вашего класса.источник
friend
Функция имеет те же права, что и функции члена ( это то , чтоfriend
означает), так как пользователь класса, я бы задаться вопросом , почему это нужно было бы что. Это различие, которое я пытаюсь провести с помощью формулировки «основные функции».Если возможно, как функции, не являющиеся членами и не являющиеся друзьями.
Как описано Хербом Саттером и Скоттом Мейерсом, предпочитайте функции-члены, не являющиеся друзьями, функциям-членам, чтобы улучшить инкапсуляцию.
В некоторых случаях, например с потоками C ++, у вас не будет выбора, и вам придется использовать функции, не являющиеся членами.
Но все же это не означает, что вы должны сделать эти функции друзьями ваших классов: эти функции могут по-прежнему получать доступ к вашему классу через ваши методы доступа к классу. Если вам удастся написать эти функции таким образом, вы выиграете.
О прототипах оператора << и >>
Я считаю, что примеры, которые вы привели в своем вопросе, неверны. Например;
Я даже не могу представить, как этот метод может работать в потоке.
Вот два способа реализации операторов << и >>.
Допустим, вы хотите использовать объект типа T, похожий на поток.
И что вы хотите извлечь / вставить из / в T соответствующие данные вашего объекта типа Paragraph.
Универсальные прототипы функций оператора << и >>
Первый как функции:
Универсальные прототипы методов оператора << и >>
Второй - как методы:
Обратите внимание, что для использования этой записи вы должны расширить объявление класса T. Для объектов STL это невозможно (вы не должны изменять их ...).
А что, если T - это поток C ++?
Вот прототипы тех же операторов << и >> для потоков C ++.
Для общих basic_istream и basic_ostream
Обратите внимание, что это случай с потоками, поскольку вы не можете изменить поток C ++, вы должны реализовать функции. Что означает что-то вроде:
Для char istream и ostream
Следующий код будет работать только для потоков на основе символов.
Рис Улерих прокомментировал тот факт, что код на основе символов является всего лишь «специализацией» общего кода над ним. Конечно, Рис прав: я не рекомендую использовать пример на основе символов. Здесь он приводится только потому, что его проще читать. Поскольку это возможно только в том случае, если вы работаете только с потоками на основе символов, вам следует избегать его на платформах, где используется код wchar_t (например, в Windows).
Надеюсь, это поможет.
источник
Он должен быть реализован как бесплатная, не дружественная функция, особенно если, как и большинство вещей в наши дни, вывод в основном используется для диагностики и ведения журнала. Добавьте константные аксессоры для всех вещей, которые должны поступать в вывод, а затем пусть средство вывода просто вызовет их и выполнит форматирование.
На самом деле я собрал все эти бесплатные функции вывода ostream в заголовке «ostreamhelpers» и файле реализации, это держит эту вторичную функциональность далеко от реальной цели классов.
источник
Подпись:
Кажется довольно подозрительным, это не соответствует
stream
ни соглашению, ни побитовому соглашению, поэтому похоже на случай злоупотребления перегрузкой оператора,operator <
должен вернуться,bool
ноoperator <<
вероятно, должен вернуть что-то еще.Если вы имели в виду, скажите:
Затем, поскольку вы не можете добавлять функции
ostream
по необходимости, функция должна быть бесплатной функцией, независимо от того,friend
зависит ли она от того, к чему она имеет доступ (если ей не нужен доступ к частным или защищенным членам, нет необходимости делать это друг).источник
ostream
что при использованииostream.operator<<(obj&)
упорядочивания потребуется доступ для изменения ; следовательно, свободная функция. В противном случае тип пользователя должен быть паровым для обеспечения доступа.В заключение хочу добавить, что вы действительно можете создать оператор
ostream& operator << (ostream& os)
внутри класса, и он может работать. Насколько я знаю, использовать его - не лучшая идея, потому что он очень запутан и не интуитивен.Предположим, у нас есть такой код:
Подводя итог - вы можете это сделать, но, скорее всего, не должны :)
источник
друг оператор = равные права как класс
источник
operator<<
реализована как функция друга:Это может быть дружественная функция только потому, что объект находится справа,
operator<<
а аргументcout
- слева. Таким образом, это не может быть функцией-членом класса, это может быть только функция друга.источник