Должен оператор <<быть реализованным как друг или как функция членства?

121
задан Robert 2 July 2015 в 10:02
поделиться

5 ответов

Проблема здесь находится в Вашей интерпретации статьи Вы ссылка .

Эта статья о ком-то, который имеет проблемы, правильно определяющие 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;
}
113
ответ дан Martin York 24 November 2019 в 01:32
поделиться

Вы не можете сделать этого как функции членства, потому что неявной this параметр является левая сторона << - оператор. (Следовательно, необходимо было бы добавить его как функцию членства к ostream - класс. Не хороший:)

Вы могли сделать это как бесплатную функцию без friend луг это? Это - то, что я предпочитаю, потому что это проясняет, что это - интеграция с ostream, и не базовая функциональность Вашего класса.

53
ответ дан Magnus Hoff 24 November 2019 в 01:32
поделиться

Это должно быть реализовано как свободный, недруг функции, особенно если, как большинство вещей в эти дни, вывод главным образом используется для диагностики и входа. Добавьте средства доступа константы для всех вещей, которые должны войти в вывод, и затем иметь outputter, просто называют тех и делают форматирование.

я на самом деле взял к сбору всех бесплатных функций вывода этих ostream в "ostreamhelpers" файле заголовка и реализации, это сохраняет ту вторичную функциональность далеко от реальной цели классов.

10
ответ дан XPav 24 November 2019 в 01:32
поделиться

Если возможно, как лицо, не являющееся членом какой-либо организации, и недруг функции.

, Как описано Herb Sutter и Scott Meyers, предпочтите недруга функции лица, не являющегося членом какой-либо организации, функциям членства, чтобы помочь увеличить инкапсуляцию.

В некоторых случаях, как потоки C++, Вы не будете иметь выбора и должны использовать функции лица, не являющегося членом какой-либо организации.

, Но тем не менее, это не означает, что необходимо завести этих друзей функций классов: Эти функции могут все еще получить доступ к Вашему классу через Ваши средства доступа класса. Если Вы преуспеваете в том, чтобы писать тем функциям этот путь, то Вы победили.

оператор About < < и>> прототипы

я верю примерам, которые Вы дали в своем вопросе, являются неправильными. Например;

ostream & operator<<(ostream &os) {
    return os << paragraph;
}

я не могу даже начать думать, как этот метод мог работать в потоке.

Вот эти два способа реализовать < < и>> операторы.

Скажем, Вы хотите использовать подобный потоку объект типа T.

И что Вы хотите извлечь/вставить из T соответствующие данные своего объекта Абзаца типа.

оператор Generic < < и>> прототипы функции

первое, являющееся как функции:

// 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 ;
}

оператор Generic < < и>> прототипы метода

второе, являющееся как методы:

// 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 это не возможно (Вы, как предполагается, не изменяете их...).

И что, если T является потоком C++?

Вот прототипы того же < < и>> операторы для потоков C++.

Для универсального basic_istream и Примечания basic_ostream

, которое является случаем потоков, поскольку Вы не можете изменить поток 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 ;
}

Для символа istream и ostream

следующий код будет работать только на основанные на символе потоки.

// 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 это поможет.

32
ответ дан paercebal 24 November 2019 в 01:32
поделиться

Подпись:

bool operator<<(const obj&, const obj&);

Кажется скорее подозреваемым, это не соответствует stream соглашение, ни поразрядное соглашение, таким образом, похоже, что случай злоупотребления перегрузки оператора, operator < должен возвратиться bool, но operator << должен, вероятно, возвратить что-то еще.

, Если Вы имели в виду так, скажите:

ostream& operator<<(ostream&, const obj&); 

Тогда, так как Вы не можете добавить функции к ostream при необходимости, функция должна быть бесплатной функцией, зависит ли она friend или не от того, к чему она должна получить доступ (если она не должна получать доступ к частным или защищенным участникам нет никакой потребности сделать ее другом).

7
ответ дан Motti 24 November 2019 в 01:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: