签名输出运算符重载

时间:2010-05-02 13:25:07

标签: c++ templates operator-overloading

你知道吗,如何为运营商写一个函数或方法的签名<<用于C ++中的模板类?我想要类似的东西:


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 个答案:

答案 0 :(得分:6)

以下所述,如果您不需要操作员成为朋友,那么请不要将其变成朋友。特别是对于输出操作员,在我看来,你不应该让他们成为朋友。这是因为如果您的类可以输出到流,它应该具有等效的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;
}