перегрузка оператора вывода подписи - PullRequest
2 голосов
/ 02 мая 2010

знаете, как написать сигнатуру функции или метода для оператора << для шаблона класса в C ++? Я хочу что-то вроде: <pre><code> template <class A> class MyClass{ public: friend ostream & operator<<(ostream & os, MyClass<A> mc); } ostream & operator<<(ostream & os, MyClass<A> mc){ // some code return os; } Но это просто не скомпилируется. Кто-нибудь знает, как правильно написать?

1 Ответ

6 голосов
/ 02 мая 2010

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

Если у вас есть веские основания для того, чтобы сделать их друзьями, вы можете определить друга

template <class A> class MyClass {
  public:
    friend ostream & operator<<(ostream & os, MyClass<A> const& mc) {
      // ...
    }
};

Таким образом, вам не нужно выражение template<...>, которое возвращает тип A. Общеизвестно, если вы определите оператор внутри шаблона. Обратите внимание, что даже если вы определили его внутри шаблона, это не функция-член. Он все еще не является членом, но имеет доступ к именам, объявленным в классе (например, параметр шаблона). Для каждого экземпляра MyClass, который вы создаете, из этой функции-друга, которая печатает вещи, создается другая не шаблонная операторная функция.

Если вы хотите определить шаблон снаружи, вы должны предварительно объявить его, чтобы иметь возможность объявить данную специализацию как друга.

// predeclare it so you can make it a friend.
template <class A> class MyClass;
template <class A> ostream &operator<<(ostream &os, MyClass<A> const&);

template <class A> class MyClass{
  public:
    /* the "<A>" is needed - it says that a given instantiation of
       that template is a friend, and not a non-template function. */
    friend ostream & operator<< <A>(ostream & os, MyClass<A> const& mc);
};

template <class A> 
ostream & operator<<(ostream & os, MyClass<A> const& mc){
  // some code
  return os;
}

Это делает operator<< <Foo> другом MyClass<Foo>. Если бы вы пропустили <A> или также возможный пустой <>, компилятор понял бы, что из сказанного вы сделали оператор не-шаблон , имеющий конкретные вместо шаблонных параметров в качестве друга.

Более простое, но менее "правильное" решение - заставить MyClass <Foo> иметь в качестве друга все operator << экземпляров. Таким образом, теоретически operator << <Bar> может получить доступ к закрытым членам MyClass <Foo>. Это не то, что нужно, но это тоже работает, получая больше доступа, чем нужно. Это избавляет от необходимости объявления форварда:

template <class A> class MyClass{
  public:
    /* make all instantiations friends. */
    template<typename T>
    friend ostream & operator<<(ostream & os, MyClass<T> const& mc);
};

template <class T> 
ostream & operator<<(ostream & os, MyClass<T> const& mc){
  // some code
  return os;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...