本文已参与「新人创作礼」活动,一起开启掘金创作之路。
我们想要将student类型,也就是自定义类型放在<<后面进行输出,这时候就要运算符重载。
<<完整函数名是operator<< ,既然是函数就能重载
#include<iostream>
using namespace std;
struct student
{
string name;
double score;
public:
student(string name, double score){
this->name = name;
this->score = score;
}
void print(){
cout << name << ' ' << score << endl;
}
string getName(){
return name;
}
double getScore(){
return score;
}
void setName(string name){
this->name = name;
}
void setScore(double score){
this->score = score;
}
};
ostream& operator<<(ostream& o, student s){
cout << s.name << " " << s.score << endl;
return o;
}
int main(){
student s1("aa", 65);
cout << s1;
return 0;
}
asdasd
在这里使用<<时实际是operator<<(cout, s1)
最后返回的是ostream,因为使用时我们会有连续使用的情况,如:cout << s1 << s2 << endl;注意返回的是引用类型。
如果要改成class就出问题了,因为属性是私有的,而输出类型运算符是外部函数
想要使用,有以下方法:
- 使用公开的函数访问
cout << s.getName() << " " << s.getScore() << endl; - 设置这个函数为友元函数,那么它就是这个类的朋友,就能访问属性
我们也可以对输入运算符重载,但为了改变对象的值,必须定义为引用类型,不然改变的只是形参这个局部变量。
friend istream &operator>>(istream &i, student &s);
我们再定义一个下标运算符,它和刚刚的两个就不一样,必须作为成员函数。
#include<iostream>
using namespace std;
class Point{
private:
double x;
double y;
public:
Point(double x, double y){
this->x = x;
this->y = y;
}
double operator[](int i){
if(i ==0){
return x;
}
else if (i==1){
return y;
}
else{
throw "越界";
}
}
};
int main(){
Point p(1, 2);
cout << p[0];
return 0;
}
但这里不能对属性进行修改
可以进行重载,定义两个函数
double operator[](int i) const{
if(i ==0){
return x;
}
else if (i==1){
return y;
}
else{
throw "越界";
}
}
double& operator[](int i){
if(i ==0){
return x;
}
else if (i==1){
return y;
}
else{
throw "越界";
}
}
为了实现重载,第一个后面可以加上const,这样两个函数的签名就不一样,加上const代表该函数不会对数据进行更改
对于+我们也可以重载,有两种形式
外部函数:
Point operator+(const Point p, const Point q){
return Point(p[0] + q[0], p[1] + q[1]);
}
本质上是operator+(p, q)
成员函数:
Point operator+(const Point q){
return Point(this->x + q[0], this->y + q[1]);
}
本质上是p.operator+(q)
有的运算符只能所谓成员函数重载,如[]
有的运算符只能作为外部函数重载,如<<
有的运算符既可以作为外部函数,也可以作为成员函数重载,如+
规则
-
并不是所有的运算符都可以重载。能够重载的运算符包括:
+ - * / % ^ & | ~ ! = < > += -= = /= %= ^= &= |= << >> <<= >>= == != <= >= && || ++ -- , -> -> () [] new new[] delete delete[]上述运算符中,[]是下标运算符,()是函数调用运算符。自增自减运算符的前置和后置形式都可以重载。长度运算符sizeof、条件运算符: ?、成员选择符.和域解析运算符::不能被重载。
-
重载不能改变运算符的优先级和结合性。
-
重载不会改变运算符的用法,原有有几个操作数、操作数在左边还是在右边,这些都不会改变。例如~号右边只有一个操作数,+号总是出现在两个操作数之间,重载后也必须如此。
-
运算符重载函数不能有默认的参数,否则就改变了运算符操作数的个数,这显然是错误的。
-
运算符重载函数既可以作为类的成员函数,也可以作为全局函数。
将运算符重载函数作为类的成员函数时,二元运算符的参数只有一个,一元运算符不需要参数。之所以少一个参数,是因为这个参数是隐含的。