签名输出运算符重载

发布于 2024-08-31 01:12:49 字数 395 浏览 5 评论 0原文

你知道如何为运算符<<编写函数或方法的签名吗? 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;
}
But this just won't compile. Do anyone know, how to write it correctly?

do you know, how to write signature of a function or method for operator<< for template class in C++? I want something like:


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


But this just won't compile. Do anyone know, how to write it correctly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦境 2024-09-07 01:12:49

下面都说了,如果你不需要某个操作员加为好友,那就不要加为好友。特别是对于输出操作员,我认为你不应该让他们成为朋友。这是因为,如果您的类可以输出到流,那么它应该具有等效的 get 函数,以编程方式提供相同的数据。在这种情况下,您可以根据这些 get 函数编写一个 operator<< 作为非友元。

如果您有充分的理由让他们成为朋友,您可以进行朋友定义

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<<MyClass 的朋友。如果您省略 或也可能是空的 <>,编译器会理解为您创建了一个非模板 运算符具有具体参数而不是模板化参数作为友元。

更简单但不太“正确”的解决方案是使 MyClass 将所有 operator << 实例化作为友元。所以理论上运算符<< 可以访问 MyClass 的私有成员。这不是我们想要的,但它也有效,获得了比需要的更多的访问权限。它消除了前向声明的需要:

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

All the below said, if you don't need an operator to be a friend, then don't make it a friend. For output operators in particular, in my opinion you should not make them friends. That is because if your class can be output to a stream, it should have equivalent get functions that provide the same data programmatically. And in that event, you can write a operator<< as a non-friend in terms of those get functions.

In case you have some good reason for making them friends, you can do a friend definition

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

That way you don't need the template<...> clause that gets you the type A. It's alreay known if you define the operator inside the template. Note that even though you defined it inside the template, it's not a member function. It's still a non-member, but has access to the names declared in the class (like the template parameter). For each instance of MyClass you create, a different non-template operator function is created out of that friend function that prints things.

If you want to define the template outside, you have to predeclare it to be able to declare a given specialization of it as a friend.

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

That makes operator<< <Foo> a friend of MyClass<Foo>. If you were to omit the <A> or an also possible empty <>, the compiler would understand that as saying you made a non-template operator having concrete instead of templated parameters as friend.

The more easy but less "correct" solution is to make MyClass <Foo> have as friend all the operator << instantiations. So theoretically operator << <Bar> could access private members of MyClass <Foo>. It's not what is wanted, but it works too, gaining more access than needed. It gets rid of the need for forward declaring:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文