四则运算符
class Person {
public:
Person() {};
Person(int a, int b)
{
this->m_A = a;
this->m_B = b;
}
// 成员函数实现 + 号运算符重载
Person operator+(const Person& p) {
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}
private:
int m_A;
int m_B;
};
// 全局函数实现 + 号运算符重载
Person operator+(const Person& p1, const Person& p2) {
Person temp(0, 0);
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p1.m_B + p2.m_B;
return temp;
}
// 成员函数和全局函数实现后的调用
Person p = p1 + p2;
// 运算符重载版本
Person operator+(const Person& p2, int val)
{
Person temp;
temp.m_A = p2.m_A + val;
temp.m_B = p2.m_B + val;
return temp;
}
// 调用
Person p = p1 + 10;
本质调用
// 成员函数
Person p = p1.operator+(p2);
// 全局函数
Person p = operator+(p1, p2);
其他运算符和
+
类似,只是注意精度别爆int
以及除法特判除数为0
情况
左移运算符
class Person {
// 设置友元,因为全局函数要使用私有变量
friend ostream& operator<<(ostream& out, Person& p);
public:
Person(){}
Person(int a, int b)
{
this->m_A = a;
this->m_B = b;
}
// 成员函数 实现不了
// void operator<<(cout) {
// }
// 直接传 cout 肯定有问题,只是方便理解,传对应的数据类型,cout 是个 ostream 输出流对象,传 ostream
// 这样是 p << cout 不是我们想要的效果,虽然用成员函数这样写实现后,我们 p << cout 也能正确输出
// 因为成员函数里本质是用 p 去调用 << 运算符
private:
int m_A;
int m_B;
};
// 全局函数实现左移重载
// ostream对象只能有一个
// 本质是 operator<< (cout, p) ----> cout << p
ostream& operator<<(ostream& cout, Person& p) {
cout << "a:" << p.m_A << " b:" << p.m_B;
return out;
}
// 这里面引用缘故,还可使用 out 起别名
ostream& operator<<(ostream& out, Person& p) {
out << "a:" << p.m_A << " b:" << p.m_B;
return out;
}
// 外部输出还是 cout
cout << p;
- 注意传参和返回值都需要引用的存在
- 因为标准输出流对象只能有一个,所以不能创建副本,返回值自然也不能传值
- 返回值传引用是因为
- 调用过程是:执行
cout << p
,左移运算符做了重载,传入cout
和p
- 然后执行函数体,就实现了重载,这里相当于是
ostream& out = cout
为了实现链式编程,返回值为
ostream&
,这样之后就可以cout << p << endl
递增运算符
class MyInteger {
friend ostream& operator<<(ostream& out, MyInteger myint);
public:
MyInteger() {
m_Num = 0;
}
// 前置++
MyInteger& operator++() {
//先++
m_Num++;
//再返回
return *this;
}
// 后置++
// int 是占位符,表示 a++
MyInteger operator++(int) {
// 先返回
// 记录当前本身的值,然后让本身的值加1,但是返回的是以前的值,达到先返回后++;
MyInteger temp = *this;
m_Num++;
return temp;
}
private:
int m_Num;
};
ostream& operator<<(ostream& out, MyInteger myint) {
out << myint.m_Num;
return out;
}
// 调用
MyInter a;
cout << ++(++a);
cout << a++;
// 不存在 cout << (a++)++;
- 前置加加返回引用是因为存在
++(++a)
这种情况,我们要实现这种,就需要返回引用 - 因为不返回引用,第一次
++a
后是创建的一个副本即新对象作为++a
的结果,那么此时再执行++a
虽然能够使++(++a)
得到正确的结果,但是a
却不是,因为第二次的加加不是在a
基础上的加,是一个新的副本 - 值返回不能是因为不能返回局部引用,第二种方式会构造局部引用
赋值运算符
class Person {
public:
Person() : m_age(nullptr){}
Person(int age) {
m_Age = new int(age);
}
//重载赋值运算符
Person& operator=(const Person &p)
{
if (m_Age != NULL) {
delete m_Age;
m_Age = NULL;
}
//编译器提供的代码是浅拷贝
//m_Age = p.m_Age;
//提供深拷贝 解决浅拷贝的问题
m_Age = new int(*p.m_Age);
//返回自身
return *this;
}
~Person()
{
if (m_Age != NULL) {
delete m_Age;
m_Age = NULL;
}
}
private:
int *m_Age;
};
// 调用
Person p1(10);
Person p2, p3;
p3 = p2 = p1;
- 注意实例化对象不初始化,需要在默认构造函数里指针指向空,不然是野指针,随意指向一块空间,此时进入拷贝构造函数,就会释放非法内存,导致崩溃
- 这是应对指针的拷贝构造函数,默认拷贝构造会造成释放同一块内存区域的问题,导致出错
- 对于这种类型的传引用,使用
const
修饰会更好,防止意外修改
关系运算符
class Person {
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
};
bool operator==(const Person & p)
{
if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
return true;
}
else {
return false;
}
}
string m_Name;
int m_Age;
};
// 调用
Person a("孙悟空", 18);
Person b("孙悟空", 18);
if(a == b)
else if(a != b)
函数调用运算符 ( )
class MyPrint {
public:
void operator()(string text) {
cout << text << endl;
}
};
// 调用
MyPrint myFunc;
myFunc("hello world");
class MyAdd {
public:
int operator()(int v1, int v2) {
return v1 + v2;
}
};
// 调用
MyAdd add;
int ret = add(10, 10);