我有一个重载输出运算符“<<”的类,我已经实现了它。但是,编译时抱怨主方法中“与运算符<< ..”不匹配。我不知道为什么它不起作用。
/*
* 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;
}
}
}
答案 0 :(得分: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<<
的唯一方法是使其成为自由函数:
class Accumulator {...};
ostream& operator<<(ostream &out, const Accumulator &accum);
这样,这样的正常通话:
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;
}
现在你不必让重载成为该类的朋友了。
答案 1 :(得分: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
类(例如专业记录器),则只能使用一个参数成员函数重载。