运算符重载
- 运算符重载的概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
(一)加号运算符重载
作用:实现两个自定义数据类型相加的运算
通过成员函数实现加号运算符的重载
案例代码如下:
#include <iostream>
#include <string>
using namespace std;
//+号运算符重载
class Person
{
public:
//通过成员函数实现运算符重载
Person operator+(Person p)
{
Person tmp;
tmp.m_A = this->m_A + p.m_A;
tmp.m_B = this->m_B + p.m_B;
return tmp;
}
int m_A;
int m_B;
};
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;
cout << "p3.m_A:" << p3.m_A << endl;
cout << "p3.m_B:" << p3.m_B << endl;
}
int main()
{
test01();
return 0;
}
通过全局函数实现加号运算符的重载
案例代码如下:
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
int m_A;
int m_B;
};
Person operator+(Person p1, Person p2)
{
Person tmp;
tmp.m_A = p1.m_A + p2.m_A;
tmp.m_B = p1.m_B + p2.m_B;
return tmp;
}
void test01()
{
Person p1;
p1.m_A = 10;
p1.m_B = 10;
Person p2;
p2.m_A = 10;
p2.m_B = 10;
//Person p3 = operator+(p1, p2);这行代码和下面的代码是等价的
Person p3 = p1 + p2;
cout << "p3.m_A:" << p3.m_A << endl;
cout << "p3.m_B:" << p3.m_B << endl;
}
int main()
{
test01();
return 0;
}
运算符重载,也可以发生函数重载
代码如下:
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
int m_A;
int m_B;
};
//下面两个加号重载的函数构成了函数重载
Person operator+(Person p1, Person p2)
{
Person tmp;
tmp.m_A = p1.m_A + p2.m_A;
tmp.m_B = p1.m_B + p2.m_B;
return tmp;
}
Person operator+(Person p, int num)
{
Person tmp;
tmp.m_A = p.m_A + num;
tmp.m_B = p.m_B + num;
return tmp;
}
void test01()
{
Person p1;
p1.m_A = 10;
p1.m_B = 10;
Person p2;
p2.m_A = 10;
p2.m_B = 10;
//Person p3 = operator+(p1, p2);这行代码和下面的代码是等价的
Person p3 = p1 + p2;
cout << "p3.m_A:" << p3.m_A << endl;
cout << "p3.m_B:" << p3.m_B << endl;
Person p4 = p1 + 10;
cout << p4.m_A << endl;
cout << p4.m_B << endl;
}
int main()
{
test01();
return 0;
}
总结
- 对于内置的数据类型的表达式的运算是不可能改变的
- 不要滥用运算符重载
(二)左移运算符重载
作用:可以输出自定义数据类型
练习代码如下:
#include <iostream>
#include <string>
using namespace std;
//左移运算符重载
class Person
{
friend ostream& operator<<(ostream& cout, Person p);
public:
Person(int a, int b)
{
m_A = a;
m_B = b;
}
private:
//无法利用成员函数重载左移运算符,因为无法实现cout在左边
int m_A;
int m_B;
};
//利用全局函数重载左移运算符
ostream& operator<<(ostream& cout, Person p)
{
cout << "m_A:" << p.m_A << " " << "m_B:" << p.m_B << endl;
return cout;
}
void test01()
{
Person p(10, 10);
cout << p << "hello world" << endl;
}
int main()
{
test01();
return 0;
}
(三)递增运算符重载
作用:通过重载递增运算符,实现自己的整型数据
练习代码如下:
#include <iostream>
using namespace std;
class MyInteger
{
friend ostream& operator<<(ostream& cout, MyInteger myint);
public:
MyInteger()
{
m_Num = 0;
}
//重载++运算符
//重载++分为 重载前置++运算符和重载后置++运算符
//前置++
MyInteger& operator++()//返回引用是为了一直对一个数据进行递增
{
m_Num++;
return *this;
}
//后置++
//后置递增一定要返回值,不然就是返回局部变量的引用,是一个非法操作
MyInteger operator++(int)//int代表的是占位参数,可以用于区分前置和后置递增
{
//先记录当时的结果
MyInteger tmp = *this;
m_Num++;
return tmp;
}
private:
int m_Num;
};
//重载左移运算符
ostream& operator<<(ostream& cout, MyInteger myint)
{
cout << myint.m_Num << endl;
return cout;
}
void test01()
{
MyInteger myint;
cout << myint << endl;
cout << ++myint << endl;
cout << myint << endl;
}
void test02()
{
MyInteger myint;
cout << myint << endl;
cout << myint++ << endl;
cout << myint << endl;
}
int main()
{
//test01();
test02();
return 0;
}
递减运算符的重载代码如下:
#include <iostream>
using namespace std;
class MyInter
{
friend ostream& operator<<(ostream& cout, MyInter myint);
public:
MyInter()
{
m_Num = 0;
}
//前置--
MyInter& operator--()
{
m_Num--;
return *this;
}
//后置--
MyInter operator--(int)
{
MyInter tmp = *this;
m_Num--;
return tmp;
}
private:
int m_Num;
};
ostream& operator<<(ostream& cout, MyInter myint)
{
cout << myint.m_Num << endl;
return cout;
}
void test01()
{
MyInter myint;
cout << myint << endl;//0
cout << myint-- << endl;//0
cout << myint << endl;//-1
cout << --myint << endl;//-2
cout << myint << endl;//-2
}
int main()
{
test01();
return 0;
}
(四)赋值运算符的重载
C++编译器至少给一个类添加四个函数
- 默认构造函数
- 默认析构函数
- 默认拷贝构造函数
- 赋值运算符重载
operator=
,对属性进行值拷贝
如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题
练习代码如下:
#include <iostream>
using namespace std;
class Person
{
public:
Person(int age)
{
m_Age = new int(age);
}
~Person()
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}
//重载赋值运算符
Person& operator=(Person& p)//返回引用是为了实现连等的操作
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
m_Age = new int(*p.m_Age);
return *this;
}
int* m_Age;
};
void test01()
{
Person p1(18);
Person p2(20);
cout << "p1的年龄为:" << *p1.m_Age << endl;
cout << "p2的年龄为:" << *p2.m_Age << endl;
p2 = p1;
cout << "p1的年龄为:" << *p1.m_Age << endl;
cout << "p2的年龄为:" << *p2.m_Age << endl;
}
int main()
{
test01();
return 0;
}
(五)关系运算符
作用:重载关系运算符,可以让两个自定义的类型对象进行比较
练习代码如下:
#include <iostream>
#include <string>
using namespace std;
//重载关系运算符
class Person
{
public:
Person(string name, int age)
{
m_Name = name;
m_Age = 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;
}
string m_Name;
int m_Age;
};
void test01()
{
Person p1("Tom", 19);
Person p2("To", 19);
if (p1 != p2)
{
cout << "p1 is not equal p2" << endl;
}
else
{
cout << "p1 is equal p2" << endl;
}
}
int main()
{
test01();
return 0;
}
(六)函数调用运算符重载
- 函数调用运算符()也可以重载
- 由于重载后使用的方式非常像函数的调用,因此称为仿函数
- 仿函数没有固定写法,非常灵活
练习代码如下:
#include <iostream>
#include <string>
using namespace std;
//函数调用运算符重载
class MyPrint
{
public:
//重载函数调用运算符
void operator()(string test)
{
cout << test << endl;
}
};
//仿函数非常灵活
class MyAdd
{
public:
int operator()(int num1, int num2)
{
return num1 + num2;
}
};
void test02()
{
MyAdd myadd;
int ret = myadd(10, 20);
cout << ret << endl;
//匿名函数对象
cout << MyAdd()(100, 100) << endl;
}
void test01()
{
MyPrint myprint;
myprint("hello world");//由于使用起来非常像函数调用,所以称其为仿函数
}
int main()
{
//test01();
test02();
return 0;
}
✨✨✨
come on!!!