2016-03-04 50 views
2

我有一个类,重载输出运算符“< <”,我已经实现它。然而,编译的主要方法是“不匹配运营商< < ..”。我不知道为什么它不起作用。重载的操作符,但仍然“不匹配的操作符”错误

/* 
* Accumulator.cpp 
* 
* 
*  
*/ 
#include <iostream> 
#include "Accumulator.h" 

using namespace std; 


Accumulator::~Accumulator() { 
    // TODO Auto-generated destructor stub 
} 

void Accumulator::operator+=(const int nbr) { 
    nbrs.push_back(nbr); 
} 

void Accumulator::undo() { 
    if (!comitted) { 
     nbrs.pop_back(); 
    } 
} 

void Accumulator::commit() { 
    lastCommit = nbrs; 
    comitted = true; 
} 

void Accumulator::rollback() { 
    nbrs = lastCommit; 
} 

ostream& Accumulator::operator<<(ostream &out, const Accumulator &accum){ 
    int sum = 0; 
    for(int nbr : nbrs){ 
     sum+= nbr; 
    } 
    out << sum; 
    return out; 
} 
int main() { 
    Accumulator accum; 
    char cmd; 
    while (cin >> cmd) { 
     switch (cmd) { 
     case 'p': 
     cout << "Sum is now " << accum << endl; 
     break; 
     case 'a': { 
      int nbr; 
      cin >> nbr; 
      accum += nbr; 
      break; 
     } 
     case 'u': 
     accum.undo(); 
     break; 
     case 'c': 
     accum.commit(); 
     break; 
     case 'r': 
     accum.rollback(); 
     break; 
    } 
} 
} 
+4

对于** member ** operator <<,参数不同。你只需要右手参数。 – Incomputable

+0

不要使其成为会员功能。 –

+1

对于二进制成员操作符,左侧是'* this',右侧是参数(只能有一个)。您不能将流操作符作为成员进行重载。 – molbdnilo

回答

2

非静态成员函数总是有一个额外的隐藏参数,它是this指针,该函数被调用的对象。因此,可以说,你有一个这样的类:

class Test { 
    public: 
     void f(int param) { 
     } 
}; 

Test t; 
t.f(10); 

呼叫t.f(10)基本上等同于在后台是这样的:Test::f(&t, 10)(注意,这是不合法的代码,它只是给你一个想法是什么发生)。

现在回到您的操作员,如果您将其设置为班级中的成员函数,则无法像通常那样调用它。这是因为调用它是这样的:

std::cout << accum; 

是相同的:

cout.operator<<(accum); 

这在背景是相同的:

Accumulator::operator<<(&cout, accum); 

,而你的成员函数是等同于这个:

ostream& operator<<(Accumulator* this, ostream &out, const Accumulator &accum); 

注意参数不匹配。

因此,只有这样,才能正确地重载operator<<是让它自由功能:

这样,正常通话这样的:

std::cout << accum; 

等效于此:

operator<<(std::cout, accum); 

它完全匹配过载声明。

如果你超载实现您需要访问您的Accumulator类的私有成员,你可以以不同的方式:让你的过载的类实例的朋友,或在你的类像这样将一个公共的功能:

class Accumulator { 
public: 
    void printToStream(ostream &out) const { 
     out << private_members; 
    } 
}; 

,并从运算符重载这样称呼它:

ostream& operator<<(ostream &out, const Accumulator &accum) { 
    accum.printToStream(out); 
    return out; 
} 

现在,你不必做超负荷类的朋友了。

+0

有趣。我没有意识到“自由功能”的概念,这对我来说有点奇怪。尽管如此,你的文章是非常丰富的,我总是很高兴学习这样的事情实际上是如何工作的,而不仅仅是“这是怎么做”的答案。非常感谢 – Alexmedkex

0

正如@n.m所示。 ,流注入器不能被重载为成员函数,而是作为2个参数的普通函数。

你.h文件中变成:

class Accumulator { 
    ... // no operator << here ! 
}; 

ostream& operator << (ostream &out, const Accumulator& accum); 

和实施:

ostream& operator << (ostream &out, const Accumulator& accum) { 
    ... 
    return out; 
} 

你只使用一个参数成员函数重载,如果你编写自定义ostream类(比如一个专门记录器)。