引言
运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。
4.5.1 加号运算符的重载
作用:实现两个自定义的数据类型相加。
#include <iostream>
#include <string>
using namespace std;
//运算符重载
//对于内置的数据类型,编译器知道如何进行运算
class Person {
public:
// 1.成员函数重载+
// Person p3 = p1.operator+(p2);
// Person operator+(Person& p)
// {
// Person temp;
// temp.m_A = this->m_A + p.m_A;
// temp.m_B = this->m_B + p.m_B;
// return temp;
// }
int m_A;
int m_B;
};
// 2.全局函数重载+
// Person p3 = operator+(p1,p2);
Person operator+(Person p1, Person p2)
{
Person temp;
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p1.m_B + p2.m_B;
return temp;
}
//函数重载的版本
Person operator+(Person& p1, int num)
{
Person temp;
temp.m_A = p1.m_A + num;
temp.m_B = p1.m_B + num;
return temp;
}
void test01()
{
Person p1;
p1.m_A = 10;
p1.m_B = 10;
Person p2;
p2.m_A = 10;
p2.m_B = 10;
// Person p3 = p1 + p2;
Person p3 = operator+(p1, p2);
cout << p3.m_A << p3.m_B << endl;
//运算符重载也可以发生函数重载
Person p4 = p1 + 100;
cout << p4.m_A << p4.m_B << endl;
}
int main()
{
test01();
return 0;
}
总结1:对于内置的数据类型的表达式是不可能改变的
总结2:不要滥用运算符的重载
4.5.2 左移运算符重载
作用:可以输出自定义的数据类型
#include <iostream>
#include <string>
using namespace std;
//运算符重载
//左移运算符 <<
// 输出自定义类型
class Person {
friend ostream& operator<<(ostream& cout, Person& p); // 声明为类的友元
private:
int m_A;
int m_B;
public:
Person()
{
m_A = 10;
m_B = 20;
}
//利用成员函数重载左移运算符 p.operator<<(cout) 简化版本 p<<cout
//不会利用成员函数重载左移运算符<< ,无法实现cout在左侧
// void operator<<(cout)
// {
// cout << this->m_A << endl;
// cout << this->m_B << endl;
// }
};
//只能用全局函数重载<<运算符
//本质operator<<(cout ,p)
//简化 cout << p
ostream& operator<<(ostream& cout, Person& p)
{
cout << p.m_A << endl;
cout << p.m_B << endl;
return cout;
}
void test01()
{
Person p;
cout << p << endl;
}
int main()
{
test01();
return 0;
}
总结:重载左移运算符配合友元可以实现输出自定义的数据类型
右移运算符重载
#include <iostream>
using namespace std;
class Student {
public:
Student(int math = 0, int english = 0, int total = 0) //代表初始值为0,可以给他赋值,传递几个参数都可以,不穿默认0。
: _math(math)
, _english(english)
, _total(total)
{
}
void show()
{
cout << _math << " " << _english << " " << _total << endl;
}
private:
int _math, _english, _total;
friend istream& operator>>(istream& in, Student& s);
};
istream& operator>>(istream& in, Student& s)
{
in >> s._math >> s._english;
s._total = s._math + s._english;
return in;
}
int main()
{
Student s;
cin >> s;
s.show();
}
4.5.3 递增运算符重载
作用:通过重载递增运算符,实现自己的整型数据
#include <iostream>
using namespace std;
//递增运算符重载++
//自定义的整型
class MyInteger {
friend ostream& operator<<(ostream& cout, MyInteger myint);
public:
MyInteger()
{
int m_Num = 0;
}
//重载++运算符
//重载分为两者,前递增
MyInteger&
operator++()
{
//先进行++运算
m_Num += 1;
//再将自身返回,返回需要返回引用,为了对一个数据进行递增.
return *this;
}
//后递增
// int代表占位参数,可以用来区分前置和后置递增
MyInteger operator++(int)
{
//先记录当时结果
MyInteger temp = *this;
//后 递增
m_Num++;
// 最后将结果返回
return temp;
}
private:
int m_Num;
};
ostream& operator<<(ostream& cout, MyInteger myint)
{
cout << myint.m_Num;
return cout;
}
void test01()
{
MyInteger myint;
cout << myint << endl;
cout << ++myint << endl;
cout << ++myint << endl;
cout << myint << endl;
}
void test02()
{
MyInteger myint;
cout << myint++ << endl;
cout << myint << endl;
}
int main()
{
test02();
return 0;
}
4.5.4 递减运算符
#include <iostream>
using namespace std;
//递减运算符重载--
//自定义的整型
class MyInteger {
friend ostream& operator<<(ostream& cout, MyInteger myint);
public:
MyInteger()
{
int m_Num = 0;
}
//重载--运算符
//重载分为两者,前递减
MyInteger&
operator--()
{
//先进行--运算
m_Num--;
//再将自身返回,返回需要返回引用,为了对一个数据进行递减
return *this;
}
//后递减
// int代表占位参数,可以用来区分前置和后置递减
MyInteger operator--(int)
{
//先记录当时结果
MyInteger temp = *this;
//后 递减
m_Num--;
// 最后将结果返回
return temp;
}
private:
int m_Num;
};
ostream& operator<<(ostream& cout, MyInteger myint)
{
cout << myint.m_Num;
return cout;
}
void test01()
{
MyInteger myint;
cout << myint << endl;
cout << --myint << endl;
cout << --myint << endl;
cout << myint << endl;
}
void test02()
{
MyInteger myint;
cout << myint-- << endl;
cout << myint << endl;
}
int main()
{
test01();
return 0;
}
4.5.5 赋值运算符重载
C++编译器至少给一个类添加4个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝函数,对属性进行值拷贝
4.赋值运算符operator=,对属性进行值拷贝
如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝的问题。
#include <iostream>
using namespace std;
//赋值运算符重载
class Person {
public:
Person(int age)
{
m_Age = new int(age);
}
int* m_Age;
//重载=赋值运算符
Person& operator=(Person& p)
{
//编译器提供浅拷贝
// m_Age = p.m_Age;
//我们应该先判断是否有属性在堆区,如果有先释放干净,然后在深拷贝
if (m_Age != NULL) {
delete m_Age;
m_Age = NULL;
}
//深拷贝操作
m_Age = new int(*p.m_Age);
//返回对象自身
return *this;
}
~Person()
{
if (m_Age != NULL) {
delete m_Age;
m_Age = NULL;
}
}
};
void test01()
{
Person p1(19);
Person p2(20);
Person p3(30);
p3 = p2 = p1; //赋值运算操作
cout << "p1的年龄" << *p1.m_Age << endl;
cout << "p2的年龄" << *p2.m_Age << endl;
cout << "p3的年龄" << *p3.m_Age << endl;
}
int main()
{
test01();
return 0;
}
4.5.6 关系运算符重载
作用:重载关系运算符,可以让两个自定义的类型对象进行比较操作。
#include <iostream>
using namespace std;
//重载关系运算符
class Person {
public:
Person(string name, int age)
{
m_Name = name;
m_Age = age;
}
string m_Name;
int m_Age;
bool operator==(Person& p)
{
if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
return true;
}
return false;
}
bool operator!=(Person& p)
{
if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
return false;
}
return true;
}
};
void test01()
{
Person p("张三", 15);
Person p2("张三s", 15);
if (p == p2) {
cout << "p和p2相等" << endl;
} else {
cout << "p和p2不相等" << endl;
}
}
int main()
{
test01();
return 0;
}
4.5.7 函数调用运算符重载
函数调用运算符()也可以重载
由于重载后使用的方法非常像函数的调用,因此称为仿函数。
仿函数没有固定的写法,非常灵活。
#include <iostream>
using namespace std;
//打印输出的类
class MyPrint {
friend void test01();
//重载函数调用运算符
void operator()(string test)
{
cout << test << endl;
}
};
void test01()
{
MyPrint p;
p("hello world"); //由于使用起来非常类似函数调用,所以我们成为仿函数
}
//仿函数非常灵活,没有固定写法
class MyAdd {
public:
int operator()(int num1, int num2)
{
return num1 + num2;
}
};
void test02()
{
MyAdd add;
cout << add(1, 2) << endl;
//匿名函数对象 类名加(),匿名对象
cout << MyAdd()(100, 10) << endl;
}
int main()
{
test02();
return 0;
}
运算符重载综合案例
#include <iostream>
using namespace std;
class complex{
public:
complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ };
public:
friend complex operator+(const complex & A, const complex & B);
friend complex operator-(const complex & A, const complex & B);
friend complex operator*(const complex & A, const complex & B);
friend complex operator/(const complex & A, const complex & B);
friend istream & operator>>(istream & in, complex & A);
friend ostream & operator<<(ostream & out, complex & A);
private:
double m_real; //实部
double m_imag; //虚部
};
//重载加法运算符
complex operator+(const complex & A, const complex &B){
complex C;
C.m_real = A.m_real + B.m_real;
C.m_imag = A.m_imag + B.m_imag;
return C;
}
//重载减法运算符
complex operator-(const complex & A, const complex &B){
complex C;
C.m_real = A.m_real - B.m_real;
C.m_imag = A.m_imag - B.m_imag;
return C;
}
//重载乘法运算符
complex operator*(const complex & A, const complex &B){
complex C;
C.m_real = A.m_real * B.m_real - A.m_imag * B.m_imag;
C.m_imag = A.m_imag * B.m_real + A.m_real * B.m_imag;
return C;
}
//重载除法运算符
complex operator/(const complex & A, const complex & B){
complex C;
double square = A.m_real * A.m_real + A.m_imag * A.m_imag;
C.m_real = (A.m_real * B.m_real + A.m_imag * B.m_imag)/square;
C.m_imag = (A.m_imag * B.m_real - A.m_real * B.m_imag)/square;
return C;
}
//重载输入运算符
istream & operator>>(istream & in, complex & A){
in >> A.m_real >> A.m_imag;
return in;
}
//重载输出运算符
ostream & operator<<(ostream & out, complex & A){
out << A.m_real <<" + "<< A.m_imag <<" i ";;
return out;
}
int main(){
complex c1, c2, c3;
cin>>c1>>c2;
c3 = c1 + c2;
cout<<"c1 + c2 = "<<c3<<endl;
c3 = c1 - c2;
cout<<"c1 - c2 = "<<c3<<endl;
c3 = c1 * c2;
cout<<"c1 * c2 = "<<c3<<endl;
c3 = c1 / c2;
cout<<"c1 / c2 = "<<c3<<endl;
return 0;
}