为什么要有运算符重载?
一些用于自定义类型,编译器不知道如何进行类型的运算。
运算符重载的本质是函数。
用两种方法实现运算符重载:
1、重载为成员函数,解释为:ObjectL.operator op(ObjectR),左边操作数ObjectL通过this指针传递,右操作数由参数Object传递
2、重载为友员函数,解释为:operator op(ObjectL,ObjectR),左右操作数都有参数传递
二元操作符,复数类举例子:
#include
#include
using namespace std;
class Complex {
friend Complex operator+(Complex &c1, Complex &c2);//友元函数实现运算符重载
public:
Complex() {
this->a = 0;
this->b = 0;
}
Complex(int a, int b) {
this->a = a;
this->b = b;
}
Complex operator+(const Complex &obj) { //成员函数实现运算符重载
Complex temp(this->a + obj.a, this->b + obj.b);
return temp;
}
/*
void operator=(const Complex &obj) { //如果这样写的话,不支持连等c1=c2=c3
this->a = obj.a;
this->b = obj.b;
}
*/
Complex & operator=(const Complex &obj) { //如果这样写的话,支持连等c1=c2=c3
this->a = obj.a;
this->b = obj.b;
return *this;
}
void print() {
printf("a+bi=%d+%di\n", this->a, this->b);
}
protected:
private:
int a;//实部
int b;//虚部
};
//友员函数实现加法
Complex operator+(Complex &c1,Complex &c2) {
Complex c(c1.a + c2.a, c1.b + c2.b);
return c;
}
void main() {
Complex c1(1, 2), c2(3, 4);
Complex c4 = c1 + c2; //运算符重载
Complex c5 = c1.operator+(c2); //成员函数运算符重载本质
Complex c6 = operator+(c1,c2); //友员函数运算符重载本质
c4.print();
c5.print();
c6.print();//以上三个结果相同
Complex c7 = c1 + c2 + c4; //为什么能链式编程,因为返回值为新的对象
c7.print();
Complex c8;
c8 = c1=c7; //链式编程
c7.print();
}
一元操作符,前置和后置:
#include
#include
using namespace std;
class Time {
friend void operator++(Time &t);//友员函数实现前置++运算符重载
friend Time operator++(Time &t, int);
public:
Time() {
this->day = 0;
this->month = 0;
this->year = 0;
}
Time(int day, int month, int year) {
this->day = day;
this->month = month;
this->year = year;
}
/*
void operator++() { //成员函数实现前置++运算符重载
this->day += 365;
this->month += 12;
this->year++;
}
Time operator++(int) {//成员函数实现后置++运算符重载
Time temp = *this;
this->day += 365;
this->month += 12;
this->year++;
return temp; //这里需要注意两个地方,
//第一int占位,代表后置++,第二记得返回没加之前的值,这是后置++语义决定的。
}
*/
void print() {
printf("year:%d month:%d day:%d\n", this->year, this->month, this->day);
}
protected:
private:
int year;
int month;
int day;
};
void operator++(Time &t) {//友员函数实现前置++运算符重载
t.day += 365;
t.month += 12;
t.year++;
}
Time operator++(Time &t, int) {
Time temp = t;
t.day += 365;
t.month += 12;
t.year++;
return temp; //这里需要注意两个地方,
//第一int占位,代表后置++,第二记得返回没加之前的值,这是后置++语义决定的。
}
void main() {
Time t;
++t;
t.print();
t++;
t.print();
}
既然成员函数可以实现运算符的重载,那么为什么还需要友员函数呢?
接下来介绍友员函数运算符重载的应用场景
#include
#include
#include
using namespace std;
class Com {
public:
friend ostream & operator<<(ostream &out, Com &c);
Com(int a, int b) {
this->a = a;
this->b = b;
}
void print(char *p) {
cout << p << endl;
cout << "a:" << this->a << " b:" << b << endl;
}
private:
int a;
int b;
};
ostream & operator<<(ostream &out, Com &c) {
out << "a:" << c.a << " b:" << c.b << endl;
return out;
}
void f() {
Com c(1, 2);
//全局函数
cout << c;
//operator<<(cout, c);
//没有方法拿到cout这个类的编码,只能用友员函数
//cout.operator(c);//这才是真正的类成员函数,但是这是表准里写好的,没办法给人家
//添加一个方法,所以这个时候,只能采用友员函数啦
//函数返回值当左值,要求返回一个引用
/*
cout << c << "abc";
s cout.operator<<(c);
s.operator<<("abc");
*/
cout << c << "abc";
}