运算符重载
运算符重载——赋予运算符具有操作自定义类型数据功能
- 运算符重载本身也是一种函数,我们有两种写法——友元类运算符重载函数和类运算符重载
- 运算符重载的实质本身就是函数调用
- 我们要注意它的写法:
- 函数返回值 :运算完成后的值决定的
函数名 : operator 加上重载运算符组成函数名 例如operator+就是重载加号
参数 :看运算符的操作数,具体参数个数是要看你重载函数形式是什么
函数体 : 写运算符具体想要的操作
对于运算符重载函数的参数友元类函数和类函数是不一样的
-
友元类的参数个数是操作数的个数
例如+是双目运算符,使用+的重载函数的参数个数就是两个
-
类重载函数的参数个数是操作数的个数减一
因为类重载函数本身还是对象来调用,所以有一个参数就在类内不需要再次传参
我们可以看到我们自己定义的类是没有办法用这些运算符的,现在我们就需要写运算符重载函数来解决这些红色波浪线
class Complex
{
public:
Complex(int a = 0, int b = 0) :a(a), b(b) {}
void print()
{
cout << a <<"\t" << b << endl;
}
friend Complex operator+(Complex& a, Complex& b); //类内定义类外实现
protected:
int a;
int b;
};
Complex operator+(Complex& a, Complex& b) {
//return Complex(a.a + b.a, a.b + b.b); //可以直接用无名对象来返回
Complex c(a.a + b.a, a.b + b.b); //也可以定义一个临时的类c,然后运算结束后再返回
return c;
}
int main()
{
Complex one(1, 1);
Complex two(2, 0);
Complex three;
three = one + two; //这里的three是一个类,所以我们可以推断重载函数的返回是一个类
three.print();
/*打印结果
3 1
*/
return 0;
}
这样,我们的加号运算符也就可以使用了(重载函数的函数体是可以根据你的想法来写的,就算你重载加号,实际的实现是相减都可以)
class Complex
{
public:
Complex(int a = 0, int b = 0) :a(a), b(b) {}
void print()
{
cout << a <<"\t" << b << endl;
}
bool operator>(Complex& object) { //这是类重载,参数个数是操作数减一
if (this->a > object.a) return 1;
else if (this->a == object.a && this->b > object.b) return 1;
else return 0;
}
protected:
int a;
int b;
};
int main()
{
Complex one(1, 1);
Complex two(2, 0);
// 这里是对两个类进行比较,我们可以推断出这是bool类型
if (two > one) cout << "two比较大" << endl;
else cout << "one比较大" << endl;
/*打印结果
two比较大
*/
return 0;
}
好了,基础的运算符就是这样重载的,而且友元重载和类重载都写了一遍,那么接下来我们来讲一个新的运算符重载
流运算符重载
-
cin类型 : istream类的对象
-
cout类型: ostream类的对象
-
流运算符 >> <<
-
必须采用友元函数形式重载
这个时候我们就需要用一种特殊的运算符重载——流运算符重载
但是我们又发现了一个问题,这种特殊的重载函数它的类型是什么呢,它该返回什么呢?
当我们不知道返回类型可以先用void类型试试,然后遇到问题再做思考
class MM {
public:
MM(string name="",int age=18):name(name),age(age){}
friend void operator>>(istream& in, MM& a);
friend void operator<<(ostream& out, MM& a);
protected:
string name;
int age;
};
void operator>>(istream& in, MM& a) { //这是输入的重载函数
in >> a.name >> a.age;
}
void operator<<(ostream& out, MM& a) { //这是输出的重载函数
out << a.name << "\t" << a.age;
}
int main()
{
MM mm;
cin >> mm;
cout << mm;
/*输入:baby 22
打印结果
baby 22
*/
return 0;
}
这里一定要记住输入输出流运算符重载函数一定要用友元类重载
我们又发现问题了,我们平时的输出不都是习惯写cout<<" "<<endl;吗,那么我们写的着重载函数可不可以这样操作,或者说我想一次性输入多个数据
显然我们是没有办法做到这样的效果的,现在我们要从输入输出流重载函数去考虑了
所以我们就知道了输入输出流重载函数的返回应该是cin和cout本身
class MM {
public:
MM(string name="",int age=18):name(name),age(age){}
friend istream& operator>>(istream& in, MM& a);
friend ostream& operator<<(ostream& out, MM& a);
protected:
string name;
int age;
};
istream& operator>>(istream& in, MM& a) { //这是输入的重载函数
in >> a.name >> a.age; //这里一定要用引用函数,因为要返回流本身
return in;
}
ostream& operator<<(ostream& out, MM& a) { //这是输出的重载函数
out << a.name << "\t" << a.age;
return out;
}
int main()
{
MM mm;
MM girl;
cin >> mm>>girl;
cout << mm <<"\t" << girl << endl;
/*输入:小红 18
小丽 20
打印结果
小红 18 小丽 20
*/
return 0;
}