覆盖结构上的二进制<<运算符

Override binary << operator on struct

本文关键字:lt 运算符 二进制 结构上 覆盖      更新时间:2023-10-16

我试图在这样一个简单的结构体上做一个覆盖:

struct Node {
    int data1;
        int data2;
    ostream& operator<<(ostream &o, const Node &n)
    {
       o << "(a: " << data1 << ", b: " << data2 << ")";
       return o;
    }
};

我得到:错误C2804: 'operator <<'参数太多

那么,如果我删除第二个参数:

    ostream& operator<<(ostream &o)

然后我得到:错误:binary '<<':找不到右操作数类型为'const Node'的操作符

这是怎么回事?

operator<<需要两个操作数。在两个类型之间定义operator<<重载函数有两种方法:

  1. 作为成员函数。这就是operator<<超载在std::basic_ostream和一些基本类型之间的定义。当使用std:cout << 10;时,它被解析为重载操作符std::basic_ostream<char>::operator<<(int)

    定义为成员函数时,操作符的LHS是类的实例。操作符的RHS是函数的实参。这就是为什么当你将它定义为成员函数时,它只能有一个参数。

  2. 作为自由函数。这就是在std::basic_ostream和自定义类型之间定义operator<<重载的方式。这些函数必须有两个参数。第一个实参是操作符的LHS,第二个实参是操作符的RHS。

    由于这个原因,您必须将std::ostream和类之间的operator<<重载定义为一个自由函数,std::ostream&作为第一个参数类型,Node const&作为第二个参数类型。
     std::ostream& operator<<(std:ostream& os, Node const& node);
    
在这种情况下,我希望标准库已经实现了一个函数:
template <typename T>
  std::ostream& operator<<(std::ostream& os, T const& t)
  {
     return t.serialize(os);
  }
那么,任何类都可以提供函数
std::ostream& serialize(std::ostream& os) const;

,并准备好像std::ostream的所有基本类型一样使用

std::ostream& operator<<(std::ostream&, ...)必须是一个自由函数

将它移出类,它将工作。

这样做的原因是在类中定义operator<<(std::ostream&)(或其他二进制操作符)意味着对象是LHS操作数。你必须写一些疯狂的东西,比如:

Node << std::cout;