оператор перегрузки‹‹ внутри класса в С++

У меня есть класс, который использует структуру, и я хочу перегрузить оператор ‹‹ для этой структуры, но только внутри класса:

typedef struct my_struct_t {
  int a;
  char c;
} my_struct;

class My_Class
{
  public:
    My_Class();
    friend ostream& operator<< (ostream& os, my_struct m);
}

Я могу скомпилировать только тогда, когда объявляю перегрузку оператора с ключевым словом friend, но тогда оператор перегружается везде в моем коде, а не только в классе. Как перегрузить оператор ‹‹ для my_struct ТОЛЬКО внутри класса?

Изменить: я хочу использовать перегруженный оператор для печати my_struct, которая является членом My_Class.


person aaronstacy    schedule 29.07.2009    source источник
comment
Но он перегружается только тогда, когда вы вызываете operator<< с my_struct, разве это не нормально?   -  person Dominic Rodger    schedule 29.07.2009
comment
Обратите внимание, что идиома typedef struct на самом деле не нужна в C++: stackoverflow.com/questions/612328/   -  person Nick Meyer    schedule 29.07.2009


Ответы (3)


Как перегрузить оператор ‹‹ для my_struct ТОЛЬКО внутри класса?

Определите это как

static std::ostream & operator<<( std::ostream & o, const my_struct & s ) { //...

or

namespace {
    std::ostream & operator<<( std::ostream & o, const my_struct & s ) { //...
}

в файле .cpp, в котором вы реализуете MyClass.

РЕДАКТИРОВАТЬ: Если вам действительно нужно охватить класс и ничего больше, определите его как частную статическую функцию в указанном классе. Это будет доступно только в этом классе и его подклассах. Однако он скроет все другие пользовательские operator<<, определенные для несвязанных классов (опять же, только внутри класса и его подклассов), если только они не могут быть найдены с помощью ADL или уже не являются членами std::ostream.

person Marc Mutz - mmutz    schedule 29.07.2009
comment
Предполагается, что один файл .cpp содержит только один класс, что часто бывает не так. - person ; 29.07.2009
comment
Это относится к большинству моих занятий. Если в файле .cpp есть второй класс, это деталь реализации основного класса, и расширенная экспозиция не имеет значения. И это помогает содержать файл .h в чистоте, что нельзя недооценивать. - person Marc Mutz - mmutz; 29.07.2009
comment
+1 Я думал, что безымянное пространство имен нарушит правила ADL, но после тестирования как с g++, так и с comeau кажется, что это не так. Хороший. - person David Rodríguez - dribeas; 29.07.2009
comment
Другая проблема, которую спрашивающий не прояснил, заключается в том, хочет ли он использовать каких-либо членов My_Class во время вывода? Если он это сделает, закрытый член - единственный реальный вариант. - person ; 29.07.2009
comment
Пространство имен anon эквивалентно namespace _unique {} using namespace _unique;, поэтому функция будет найдена, вне зависимости от ADL. - person Marc Mutz - mmutz; 29.07.2009
comment
@Neil: my_struct отличается от MyClass, так зачем operator<< для my_struct использовать закрытые члены MyClass? - person Marc Mutz - mmutz; 29.07.2009
comment
+1. Я согласен с Нилом в том, что это решение имеет ограничение, заключающееся в том, что оно предполагает, что один файл .cpp содержит только один класс. Однако С++ не предоставляет особенно чистого способа сделать то, что задает вопрос. Лично я считаю, что определение области действия в файле реализации .cpp часто работает достаточно хорошо и, вероятно, является малоиспользуемым методом. Я думаю, что у большинства людей, изучающих C и C++, сложилось впечатление, что вы должны поместить все определения областей имен в файл .h, а не стремиться к чистым и минимально определенным интерфейсам. - person Marsh Ray; 29.07.2009
comment
@mmutz Он хочет связать это с классом - для этого должна быть какая-то причина. Возможно, MyClass содержит какие-то специальные инструкции по форматированию — кто знает? - person ; 29.07.2009

Не используйте оператор ‹‹. Используйте именованную функцию-член и сделайте ее частной.

class My_Class
{
  public:
    My_Class();
 private:
    void Print( ostream & os, const my_struct & m );
};

Обратите внимание, что вы должны передавать структуру как константную ссылку, какой бы метод вы ни использовали.

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

person Community    schedule 29.07.2009

Если под «перегруженным только в My_Class» вы подразумеваете видимый/используемый только моим классом, вы можете использовать перегрузку, не являющуюся членом, которая видна только My_Class. Например.

   struct my_struct {
      int a;
      char c;
   };

   class My_Class
   {
      publiC:
         My_Class();
   }

Затем в My_Class.cpp:

namespace {
    ostream& operator(ostream& os, const my_struct& mystruct ) {
         os << mystruct.a << mystruct.c;
    }
}
person maccullt    schedule 29.07.2009
comment
Почему вы удаляете и восстанавливаете ответы, которые говорят одно и то же? - person ; 29.07.2009
comment
Я хотел отредактировать и каким-то образом получил копию ответа. Поэтому я удалил первый. Затем вопрос изменился, поэтому я удалил свой второй и собирался добавить третий ответ, но SO предложил мне отредактировать существующий, поэтому я восстановил первый и отредактировал, к тому времени он был вашим клоном :-( - person maccullt; 29.07.2009