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

时间:2014-05-07 04:07:11

标签: c++ visual-studio-2010

我试图对这样的简单结构进行覆盖:

struct Node {
    int data1;
        int data2;

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

我得到:错误C2804:'operator&lt;&lt;'参数太多

所以,如果我删除第二个参数:

    ostream& operator<<(ostream &o)

然后我得到:错误:二进制'&lt;&lt;&lt;' :找不到哪个运算符采用'const Node'类型的右手操作数

这里发生了什么?

2 个答案:

答案 0 :(得分:3)

std::ostream& operator<<(std::ostream&, ...)需要是一个免费功能。

将它移到课堂外,它会起作用。

之所以如此,是因为在类中定义operator<<(std::ostream&)(或其他二元运算符)意味着该对象是LHS操作数。你必须像以下一样疯狂地写作:

Node << std::cout;

答案 1 :(得分:3)

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

  1. 作为会员功能。这就是operator<<与某些基本类型之间的std::basic_ostream重载的定义方式。当您使用std:cout << 10;时,它会被解析为重载运算符std::basic_ostream<char>::operator<<(int)

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

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

    出于这个原因,您必须将operator<<和您的类之间的std::ostream重载定义为自由函数,其中std::ostream&为第一个参数类型,Node const&为第二种参数类型。

    std::ostream& operator<<(std:ostream& os, Node const& node);
    
  3. 在这些时候,我希望标准库实现了一个功能:

    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一样使用所有基本类型。