Проблема здесь находится в Вашей интерпретации статьи Вы ссылка .
Эта статья о ком-то, который имеет проблемы, правильно определяющие bool операторы отношений.
оператор:
Эти операторы должны возвратить bool, поскольку они сравнивают два объекта того же типа. Является обычно самым легким определить эти операторы как часть класса. Это вызвано тем, что класс является автоматически другом себя так, объекты Абзаца типа могут исследовать друг друга (даже каждый члены парламента, не занимающие официального поста других).
существует аргумент в пользу того, чтобы сделать эти бесплатные постоянные функции, поскольку это позволяет автоматическому преобразованию преобразовать обе стороны, если они не тот же тип, в то время как функции членства только позволяют rhs быть автоматический преобразованный. Я нахожу это бумажным аргументом человека, поскольку Вы действительно не хотите автоматическое преобразование, происходящее во-первых (обычно). Но если это - что-то, что Вы хотите (я не рекомендую его), тогда создание компараторов, свободное положение может быть выгодным.
потоковые операторы:
, Когда Вы используете их в качестве потоковых операторов (а не двоичный сдвиг), первый параметр является потоком. Так как у Вас нет доступа к потоковому объекту (не Ваш для изменения), они не могут быть членскими операторами, они должны быть внешними к классу. Таким образом они должны или быть друзьями класса или иметь доступ к открытому методу, который сделает потоковую передачу для Вас.
Это также традиционно для этих объектов возвратить ссылку на потоковый объект, таким образом, можно объединить операции с потоками в цепочку вместе.
#include <iostream>
class Paragraph
{
public:
explicit Paragraph(std::string const& init)
:m_para(init)
{}
std::string const& to_str() const
{
return m_para;
}
bool operator==(Paragraph const& rhs) const
{
return m_para == rhs.m_para;
}
bool operator!=(Paragraph const& rhs) const
{
// Define != operator in terms of the == operator
return !(this->operator==(rhs));
}
bool operator<(Paragraph const& rhs) const
{
return m_para < rhs.m_para;
}
private:
friend std::ostream & operator<<(std::ostream &os, const Paragraph& p);
std::string m_para;
};
std::ostream & operator<<(std::ostream &os, const Paragraph& p)
{
return os << p.to_str();
}
int main()
{
Paragraph p("Plop");
Paragraph q(p);
std::cout << p << std::endl << (p == q) << std::endl;
}
Вы не можете сделать этого как функции членства, потому что неявной this
параметр является левая сторона <<
- оператор. (Следовательно, необходимо было бы добавить его как функцию членства к ostream
- класс. Не хороший:)
Вы могли сделать это как бесплатную функцию без friend
луг это? Это - то, что я предпочитаю, потому что это проясняет, что это - интеграция с ostream
, и не базовая функциональность Вашего класса.
Это должно быть реализовано как свободный, недруг функции, особенно если, как большинство вещей в эти дни, вывод главным образом используется для диагностики и входа. Добавьте средства доступа константы для всех вещей, которые должны войти в вывод, и затем иметь outputter, просто называют тех и делают форматирование.
я на самом деле взял к сбору всех бесплатных функций вывода этих ostream в "ostreamhelpers" файле заголовка и реализации, это сохраняет ту вторичную функциональность далеко от реальной цели классов.
, Как описано Herb Sutter и Scott Meyers, предпочтите недруга функции лица, не являющегося членом какой-либо организации, функциям членства, чтобы помочь увеличить инкапсуляцию.
В некоторых случаях, как потоки C++, Вы не будете иметь выбора и должны использовать функции лица, не являющегося членом какой-либо организации.
, Но тем не менее, это не означает, что необходимо завести этих друзей функций классов: Эти функции могут все еще получить доступ к Вашему классу через Ваши средства доступа класса. Если Вы преуспеваете в том, чтобы писать тем функциям этот путь, то Вы победили.
я верю примерам, которые Вы дали в своем вопросе, являются неправильными. Например;
ostream & operator<<(ostream &os) {
return os << paragraph;
}
я не могу даже начать думать, как этот метод мог работать в потоке.
Вот эти два способа реализовать < < и>> операторы.
Скажем, Вы хотите использовать подобный потоку объект типа T.
И что Вы хотите извлечь/вставить из T соответствующие данные своего объекта Абзаца типа.
первое, являющееся как функции:
// T << Paragraph
T & operator << (T & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// T >> Paragraph
T & operator >> (T & p_oInputStream, const Paragraph & p_oParagraph)
{
// do the extraction of p_oParagraph
return p_oInputStream ;
}
второе, являющееся как методы:
// T << Paragraph
T & T::operator << (const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return *this ;
}
// T >> Paragraph
T & T::operator >> (const Paragraph & p_oParagraph)
{
// do the extraction of p_oParagraph
return *this ;
}
Примечание, что для использования этой нотации необходимо расширить объявление класса T. Для объектов STL это не возможно (Вы, как предполагается, не изменяете их...).
Вот прототипы того же < < и>> операторы для потоков C++.
, которое является случаем потоков, поскольку Вы не можете изменить поток C++, необходимо реализовать функции. Что означает что-то как:
// OUTPUT << Paragraph
template <typename charT, typename traits>
std::basic_ostream<charT,traits> & operator << (std::basic_ostream<charT,traits> & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// INPUT >> Paragraph
template <typename charT, typename traits>
std::basic_istream<charT,traits> & operator >> (std::basic_istream<charT,traits> & p_oInputStream, const CMyObject & p_oParagraph)
{
// do the extract of p_oParagraph
return p_oInputStream ;
}
следующий код будет работать только на основанные на символе потоки.
// OUTPUT << A
std::ostream & operator << (std::ostream & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// INPUT >> A
std::istream & operator >> (std::istream & p_oInputStream, const Paragraph & p_oParagraph)
{
// do the extract of p_oParagraph
return p_oInputStream ;
}
Rhys Ulerich прокомментировал о факте, основанный на символе код является всего лишь "специализацией" универсального кода выше его. Конечно, Rhys прав: Я не рекомендую использование основанного на символе примера. Это только дано здесь, потому что более просто читать. Поскольку это только жизнеспособно, если Вы только работаете с основанными на символе потоками, необходимо избежать его на платформах, где код wchar_t распространен (т.е. в Windows).
Hope это поможет.
Подпись:
bool operator<<(const obj&, const obj&);
Кажется скорее подозреваемым, это не соответствует stream
соглашение, ни поразрядное соглашение, таким образом, похоже, что случай злоупотребления перегрузки оператора, operator <
должен возвратиться bool
, но operator <<
должен, вероятно, возвратить что-то еще.
, Если Вы имели в виду так, скажите:
ostream& operator<<(ostream&, const obj&);
Тогда, так как Вы не можете добавить функции к ostream
при необходимости, функция должна быть бесплатной функцией, зависит ли она friend
или не от того, к чему она должна получить доступ (если она не должна получать доступ к частным или защищенным участникам нет никакой потребности сделать ее другом).