运算符重载概念:对已有运算符重新定义,赋予其另一种功能,以适应不同的数据类型。
作用:实现两个自定义数据类型相加的运算。
目录
加号运算符重载
1.成员函数重载+
2.全局函数重载+
左移运算符重载<<
递增运算符重载
赋值运算符重载
关系运算符重载
函数调用运算符重载
加号运算符重载
1.成员函数重载+
#include<iostream>
#include<string>
using namespace std;
//加号运算符重载
class person
{
public:
//1.成员函数重载+
person operator + (person &p)//传入一个person类
{
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;
};
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_b;
}
int main()
{
test01();
system("pause");
return 0;
}
2.全局函数重载+
#include<iostream>
#include<string>
using namespace std;
//加号运算符重载
class person
{
public:
int m_a;
int m_b;
};
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;
}
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_b;
}
//2.全局函数重载+
int main()
{
test01();
system("pause");
return 0;
}
//成员函数重载本质调用
person p3 = p1.operator +(p2);
//全局函数重载本质调用
person p3 = operator+(p1, p2);
//简化版
person p3=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;
}
总结1:对于内置的数据的表达式运算符是不可能改变的
//最好只改变自定义类型表达式运算符
总结2:不要滥用运算符重载
左移运算符重载<<
作用:可以输出自定义的数据类型
#include<iostream>
#include<string>
using namespace std;
//左移运算符重载
class person
{
public:
int m_a;
int m_b;
};
//只能利用全局函数重载左移运算符
ostream& operator<<(ostream& nixx, person& p)
{//本质 operator<<(cout,p) ,简化 cout<<p
nixx << p.m_a << " " << p.m_b ;
return nixx;
}
void test01()
{
person p;
p.m_a = 10;
p.m_b = 10;
cout << p<<" i want to play LOL"<<endl;
}
int main()
{
test01();
system("pause");
return 0;
}
递增运算符重载
作用:通过重载递增运算符,实现自己的整型数据
//重载++运算符,++a
myinteger& operator++()//如果返回 值,myint就只能进行一次递增
{
m_num++;
return *this;//返回自身
}
myinteger operator++(int)//int代表一个占位参数,可以用于区分前置和后置递增
{
//先记录当时结果
myinteger temp = *this;
//后 递增
m_num++;
//最后将记录结果做返回
return temp;
}
#include<iostream>
#include<string>
using namespace std;
//重载递增运算符
//
//自定义整型
class myinteger
{
friend ostream& operator<<(ostream& cout, myinteger myint);
public:
myinteger()
{
m_num = 0;
}
//重载++运算符,++a
myinteger& operator++()//如果返回 值,myint就只能进行一次递增
{
m_num++;
return *this;//返回自身
}
//重载++运算符,a++
//后置递增一定要返回值
myinteger operator++(int)//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;
}
void test02()
{
myinteger myint;
cout << myint++ << endl;;
cout << myint << endl;
}
int main()
{
//test01();
test02();
system("pause");
return 0;
}
要注意,前置递增是返回引用,后置递增则返回值。
同时后置递增时,左移运算符重载时要把()里的第二个参数的&去掉。
并且,由于这一点,后置递增不适用于链式编程。
练习了一下递减运算符重载,理解了就很好敲。
#include<iostream>
#include<string>
using namespace std;
class myinteger
{
friend ostream& operator << (ostream& cout, myinteger myint);
public:
myinteger()
{
m_num = 8;
}
myinteger& operator--()
{
this->m_num--;
return *this;//返回自身
}
myinteger operator--(int)
{
myinteger temp = *this;
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;
}
void test02()
{
myinteger myint;
cout << myint-- << endl;
cout << myint << endl;
}
int main()
{
//test01();
test02();
system("pause");
return 0;
}
赋值运算符重载
C++编译器至少给一个类添加4个函数
1.默认构造函数(无参,函数体为空
2.默认析构函数(无参,函数体为空
3.默认拷贝函数,对属性进行值拷贝
4.赋值运算符 operator=,对属性进行值拷贝
如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题
#include<iostream>
#include<string>
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);
person p3(30);
p3 = p2 = p1;//赋值运算,简单的浅拷贝
//指向同一块内存,导致后续内存重复释放,因此我们要利用深拷贝解决浅拷贝带来的问题
cout << *p1.m_age<<endl;
cout << *p2.m_age << endl;
cout << *p3.m_age << endl;
}
int main()
{
test01();
system("pause");
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;
}
string m_name;
int m_age;
};
void test01()
{
person p1("胡图图",3);
person p2("胡英俊", 3);
if (p1 == p2)
{
cout << "same" << endl;
}
else cout << "different" << endl;
}
int main()
{
test01();
system("pause");
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 test01()
{
myprint print;
print("hello hututu");
myadd add;
cout<<add(78, 98)<<endl;
//匿名函数对象
cout << myadd()(100, 100) << endl;//即不先创建一个myadd类,匿名对象执行完立即释放
//通过一个类型和()会创建一个匿名对象
}
int main()
{
test01();
system("pause");
return 0;
}