1. 运算符重载
运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。(运算符重载不能改变本来寓意,不能改变基础类型寓意)
运算符重载(operator overloading)只是一种”语法上的方便”,也就是它只是另一种函数调用的方式。
在c++中,可以定义一个处理类的新运算符。这种定义很像一个普通的函数定义,只是函数的名字由关键字operator及其紧跟的运算符组成。差别仅此而已。它像任何其他函数一样也是一个函数,当编译器遇到适当的模式时,就会调用这个函数。
语法:
定义重载的运算符就像定义函数,只是该函数的名字是operator@,这里的@代表了被重载的运算符。函数的参数中参数个数取决于两个因素。
- 运算符是一元(一个参数)的还是二元(两个参数);
- 运算符被定义为全局函数(对于一元是一个参数,对于二元是两个参数)还是成员函数(对于一元没有参数,对于二元是一个参数-此时该类的对象用作左耳参数)
总结:
- 运算符重载,就是对已有的运算符重新进行定义,赋予其一种功能,以适应不同的数据类型
- 运算符重载的目的是让语法更加简洁
- 运算符重载不能改变本来寓意,不能改变基础类型寓意
- 运算符重载的本质是另一种函数调用(是编译器去调用)
- 这个函数统一的名字叫operator
- 重载函数可以写成全局函数或成员函数
- 重载函数如果写成全局的,那么双目运算符左边的是第一个参数,右边是第二个参数
- 重载函数如果写成成员函数,那么双目运算符的左边是this,右边是第一个参数
- 不能改变运算符的参数个数,不能改变运算符的优先级
2. 可重载运算符

除了赋值号(=)外,基类中被重载的操作符都将被派生类继承。
特殊运算符
- =, [], () 和 -> 操作符只能通过成员函数进行重载
- << 和 >> 操作符最好通过友元函数进行重载
- 不要重载 && 和 || 操作符,因为无法实现短路规则
常规建议

3. 运算符重载碰上友元函数
案例: 重载左移操作符(<<),使得cout可以输出对象。
class Person{
friend ostream& operator<<(ostream& os, Person& person);
public:
Person(int id,int age){
mID = id;
mAge = age;
}
private:
int mID;
int mAge;
};
ostream& operator<<(ostream& os, Person& person){
os << "ID:" << person.mID << " Age:" << person.mAge;
return os;
}
int main(){
Person person(1001, 30);
//cout << person; //cout.operator+(person)
cout << person << " | " << endl;
return EXIT_SUCCESS;
}
友元函数和一般函数主要区别在于友元函数可以访问某个类的私有数据
4. 加号运算法重载
两个相同对象相加
// 两个相同对象相加
class Maker
{
public:
int id;
int age;
public:
Maker(int id, int age)
{
this->id = id;
this->age = age;
}
// 成员函数 运算符重载
Maker operator+(Maker &m2)
{
Maker temp(this->id + m2.id, this->age + m2.age);
return temp;
}
void printMaker()
{
cout << "id = " << this->id << " age = " << this->age << endl;
}
};
// 2. 编译器调用operator+ 函数
// 3. 编译器检查参数是否对应,第一参数是加号的左边,第二个参数是加号的右边
// // 全局的函数重载
// Maker operator+(Maker &m1,Maker &m2){
// Maker temp(m1.id+m2.id,m1.age+m2.age);
// return temp;
// }
void test01()
{
Maker m1(1, 20);
Maker m2(2, 22);
Maker m3 = m1 + m2; // 1. 编译器看到两个对象相加,那么编译器会去找有没有叫operator+的函数
m3.printMaker();
Maker m4 = m1 + m2 + m3; // m3+m2 再加上 m1
m4.printMaker();
}
两个不同对象相加
class Student
{
public:
Student(int id)
{
this->id = id;
}
public:
int id;
};
class Maker
{
public:
Maker(int id, int age)
{
this->id = id;
this->age = age;
}
// // 成员函数 运算符重载
// Maker operator+(Maker &m2) {
// Maker temp(this->id+m2.id,this->age+m2.age);
// return temp;
// }
public:
int id;
int age;
};
// 全局
Maker operator+(Maker &p, Student &s)
{
// 不能使用引用
// 不能引用一个局部变量
Maker tmp(p.id + s.id, 20);
return tmp;
}
Maker operator+(Student &s, Maker &p)
{
Maker tmp(p.id + s.id, 20);
return tmp;
}
Maker operator+(Maker &p1, Maker &p2)
{
Maker tmp(10, 20);
return tmp;
}
void test01()
{
Maker p1(1, 18);
Student s1(2);
Maker p2 = p1 + s1;
cout << p2.id << endl;
Maker p3 = p2 + p1;
cout << p3.id << endl;
}
5. 减号运算符重载
class Maker
{
public:
int id;
public:
Maker(int id)
{
this->id = id;
}
Maker operator-(Maker &m2)
{
Maker tmp(this->id - m2.id);
return tmp;
}
// Maker operator-(int a){
// Maker tmp(this->id - a);
// return tmp;
// }
};
Maker operator-(Maker &m1,int val) {
Maker tmp(m1.id - val);
return tmp;
}
void test01()
{
Maker m1(10);
Maker m2(15);
Maker m3 = m2 - m1;
cout << m3.id << endl;
Maker m4 = m3-2;
cout << m4.id << endl;
}
6. 左移运算符重载 <<
1.cout是对象,<<是左移运算符
2.重载左移运算符是为了直接打印对象
3.形参和实参是一个对象(引用)
4.不能改变库类中的代码
5.ostream中把拷贝构造函数私有化了
6.如果要和endl一起使用,要返回ostream对象
class Maker
{
public:
Maker(int a, string name)
{
this->id = a;
this->name = name;
}
public:
int id;
string name;
};
ostream &operator<<(ostream &os, Maker &m)
{
cout << "id = " << m.id << " name = " << m.name << endl;
return os;
}
void test01()
{
Maker m(10, "Emily");
cout << m << endl;
cout << 10 << endl; // 内部重载了基础类型
}
class Maker2
{
// 如果要访问类的私有成员,把<<重载申明为类的友元函数
friend ostream & operator<<(ostream &os,Maker2 &m);
private:
int id;
string name;
public:
Maker2(int id, string name)
{
this->id = id;
this->name = name;
};
};
ostream & operator<<(ostream &os,Maker2 &m) {
cout << "name = " << m.name << " id = " << m.id;
return os;
}
void test02() {
Maker2 m(18,"Emily");
cout << m << endl;
}
7. 右移运算符重载 >>
// >> 运算符重载
class Maker
{
public:
string name;
int id;
public:
Maker(string name, int id)
{
this->id = id;
this->name = name;
};
};
istream &operator>>(istream &is, Maker &m)
{
cin >> m.name;
cin >> m.id;
return is;
}
void test01()
{
Maker m1("Emily", 18);
Maker m2("Emily2", 18);
cin >> m1 >> m2;
cout << "id = " << m1.id << " name = " << m1.name << endl;
cout << "id = " << m2.id << " name = " << m2.name << endl;
}
网友评论