重载运算符,但仍然“不匹配运算符”错误

时间:2016-03-04 10:00:49

标签: c++

我有一个重载输出运算符“<<”的类,我已经实现了它。但是,编译时抱怨主方法中“与运算符<< ..”不匹配。我不知道为什么它不起作用。

/*
 * 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;
    }
}
}

2 个答案:

答案 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类(例如专业记录器),则只能使用一个参数成员函数重载。