2014-05-07 43 views
2

我试着做一个简单的结构是这样的覆盖:对结构覆盖二进制运算符<<

struct Node { 
    int data1; 
     int data2; 

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

即时得到:错误C2804:“运营商< <”太多参数

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

ostream& operator<<(ostream &o) 

然后我得到:错误:二进制“< <”:没有操作员发现这需要一个合适的娴类型d操作数“常量节点”

这到底是怎么来的?

回答

3

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

移动它的类之外,它会工作。

它之所以如此是因为定义operator<<(std::ostream&)(或其他二元运算)里面的类意味着对象是LHS操作数。你将不得不写如下疯狂的:

Node << std::cout; 
+0

或者声明它作为一个'friend'和访问'data1'和'data2'通过'N'。 – user657267

+0

@ user657267我从来不喜欢那个招数太多:) – Anycorn

+0

如果需要访问类的私有数据字段,那么你只会把它变成一个“好友”函数。否则,它不必要地违反封装。 @user –

3

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

  1. 作为成员函数。这就是如何定义std::basic_ostream和一些基本类型之间的重载operator<<。当您使用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一样用于所有基本类型。