在我正在开展的项目中,我有一个Score
课程,定义如下score.h
。我试图超载它,因此,当对其执行<<
操作时,会打印_points + " " + _name
。
这是我试图做的事情:
ostream & Score::operator<< (ostream & os, Score right)
{
os << right.getPoints() << " " << right.scoreGetName();
return os;
}
以下是返回的错误:
score.h(30) : error C2804: binary 'operator <<' has too many parameters
(此错误实际上出现了4次)
我设法通过将重载声明为友元函数来实现它:
friend ostream & operator<< (ostream & os, Score right);
从score.cpp中的函数声明中删除Score::
(实际上没有将其声明为成员)。
为什么这样做,但前一段代码没有?
谢谢你的时间!
修改
我删除了对头文件重载的所有提及...但是我得到以下(并且只有)错误。 binary '<<' : no operator found which takes a right-hand operand of type 'Score' (or there is no acceptable conversion)
为什么我的测试在main()中找不到合适的重载? (这不是包括,我查了一下)
以下是完整得分。
#ifndef SCORE_H_
#define SCORE_H_
#include <string>
#include <iostream>
#include <iostream>
using std::string;
using std::ostream;
class Score
{
public:
Score(string name);
Score();
virtual ~Score();
void addPoints(int n);
string scoreGetName() const;
int getPoints() const;
void scoreSetName(string name);
bool operator>(const Score right) const;
private:
string _name;
int _points;
};
#endif
答案 0 :(得分:57)
注意:您可能需要查看operator overloading FAQ。
二元运算符可以是左侧参数类的自由函数或自由函数。 (某些运算符,如赋值,必须是成员。)由于流运算符的左侧参数是流,因此流运算符必须是流类或自由函数的成员。对任何类型实现operator<<
的规范方法是:
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// stream obj's data into os
return os;
}
请注意, 不 是会员功能。另请注意,每个const
引用都会传输对象。那是因为您不想复制对象以便对其进行流式处理,并且您不希望流式传输也改变它。
有时您想要通过类的公共接口流式传输内部无法访问的对象,因此操作员无法获取它们。然后你有两个选择:将一个公共成员放入进行流式传输的类
class T {
public:
void stream_to(std::ostream&) const {os << obj.data_;}
private:
int data_;
};
并从运营商那里打电话:
inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
obj.stream_to(os);
return os;
}
或让运营商成为friend
class T {
public:
friend std::ostream& operator<<(std::ostream&, const T&);
private:
int data_;
};
以便它可以访问类的私有部分:
inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
os << obj.data_;
return os;
}
答案 1 :(得分:9)
假设你想为+
编写一个运算符重载,这样你就可以相互添加两个Score
个对象,另一个可以向{{1}添加int
第三个,以便您可以Score
添加Score
。 int
是第一个参数的那个可以是Score的成员函数。但Score
是第一个参数的那个不能成为int
的成员函数,对吗?为了帮助您,您可以将它们写为免费功能。这就是这个int
运算符所发生的情况,你不能将成员函数添加到<<
,所以你编写了一个自由函数。当你拿走ostream
部分时,这意味着什么。
现在为什么它必须是Score::
?它没有。您只需要调用公共方法(friend
和getPoints
)。你看到很多朋友操作符,因为他们喜欢直接与私有变量交谈。我这样做是可以的,因为它们是由维护课程的人编写和维护的。只是不要让朋友部分与成员函数vs免费功能部分混淆。
答案 2 :(得分:6)
当operator<<
是示例中的成员函数时,您会收到编译错误,因为您创建的operator<<
将Score
作为第一个参数(方法的对象)被调用),然后在最后给它一个额外的参数。
当您调用一个声明为成员函数的二元运算符时,表达式的左侧是调用该方法的对象。例如a + b
可能会这样:
A a;
B b
a.operator+(b)
通常最好使用非成员二元运算符(在某些情况下 - 例如operator<<
ostream
是唯一的方法。在这种情况下,a + b
可能像这样工作:
A a;
B b
operator+(a, b);
这是一个完整的例子,展示了这两种方式; main()将输出'55'三次:
#include <iostream>
struct B
{
B(int b) : value(b) {}
int value;
};
struct A
{
A(int a) : value(a) {}
int value;
int operator+(const B& b)
{
return this->value + b.value;
}
};
int operator+(const A& a, const B& b)
{
return a.value + b.value;
}
int main(int argc, char** argv)
{
A a(22);
B b(33);
std::cout << a + b << std::endl;
std::cout << operator+(a, b) << std::endl;
std::cout << a.operator+(b) << std::endl;
return 0;
}