运算符重载
- 概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。
加号运算符重载
- 作用:实现两个自定义数据类型相加的运算
- 1、成员函数重载 + 号
成员函数重载本质调用:
person p3 = p1.operator+(p2);
- 2、全局函数重载 + 号
全局函数重载本质调用:
person p3 = operator+(p1,p2);
#include <iostream>
using namespace std;
class person {
public:
//1、成员函数实现 + 号运算符重载
/*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 operator+(const person& p1, const 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 test() {
person p1;
p1.m_a = 10;
p1.m_b = 10;
person p2;
p2.m_a = 20;
p2.m_b = 20;
person p3 = p1 + p2;
cout << "p3.m_a = " << p3.m_a << endl;
cout << "p3.m_b = " << p3.m_b << endl;
//运算符重载也可以用于函数重载
person p4 = p1 + 100;//person + int
cout << "p4.m_a = " << p4.m_a << endl;
cout << "p4.m_b = " << p4.m_b << endl;
}
int main(void)
{
test();
return 0;
}
总结:
1、对于内置的数据类型的表达式的运算符是不可能发生改变的。
2、不要滥用运算符重载。
左移运算符重载
1、一般不用成员函数实现左移运算符重载,因为它不能将变量置于<<符号的右边。
2、全局函数可以实现左移运算符的重载。
#include <iostream>
using namespace std;
class person {
friend ostream& operator<<(ostream& out, person& p);//友元的应用
public:
person(int a, int b)
{
this->m_a = a;
this->m_b = b;
}
private:
int m_a;
int m_b;
};
//全局函数实现左移重载,ostream对象只能有一个
ostream& operator<<(ostream & out, person & p)//cout为ostream类型
{
out << "a:" << p.m_a << " b:" << p.m_b << " ";
return out;//有返回值以便实现链式编程
}
void test()
{
person p1(10,20);
cout << p1 << "hello world" << endl;//可以直接输出对象,链式编程
}
int main(void)
{
test();
return 0;
}
总结:重载左移运算符配合友元可以实现输出自定义数据类型。
递增运算符重载
- 作用:通过重载递增运算符,实现自己的整形数据。
#include <iostream>
using namespace std;
class myintger{
public:
friend ostream& operator<<(ostream& cout, myintger p);//应用友元
myintger() {
m_num = 0;
}
//重载前置++运算符,返回引用为了一直对一个数据进行递增
//如果不返回引用则会在下次使用++运算符时对新的对象进行操作,导致++失败。
myintger& operator++() {
m_num++;//先进行++运算
return *this;//再将自身做返回
}
//重载后置++运算符
myintger operator++(int){//使用占位参数来达到函数重载的目的
myintger temp = *this;//先记录当时结果
m_num++;//后递增
return temp;//最后将记录结果返回
//此处返回的是局部对象,当前操作执行完即被释放。后面再返回则会是非法操作。
}
private:
int m_num;
};
ostream& operator<<(ostream& cout,myintger p){//重载左移运算符
cout << p.m_num;
return cout;
}
void test()
{
myintger p;
myintger p1;
cout << ++(++p) << endl;//2
cout << p << endl;//2
cout << p1++ << endl;//0
cout << p1 << endl;//1
}
int main(void)
{
test();
return 0;
}
总结:前置递增返回引用,后置递增返回值。
赋值运算符重载
C++编译器至少给一个类添加4个函数
1、默认构造函数(无参,函数体为空)
2、默认析构函数(无参,函数体为空)
3、默认拷贝构造函数,对属性进行值拷贝。
4、赋值运算符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)//重载赋值运算符
//编译器提供的代码是浅拷贝
//m_age = p.m_age
{//先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
if (m_age != NULL) {
delete m_age;
m_age = NULL;
}
m_age = new int(*p.m_age);//提供深拷贝,解决浅拷贝带来的问题。
return *this;//返回本身
}
int* m_age;
};
void test()
{
person p1(18);
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(void)
{
test();
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_age == p.m_age && this->m_name == p.m_name) {
return true;
}
else {
return false;
}
}
string m_name;
int m_age;
};
void test()
{
person p1("Tom",18);
person p2("Jerry", 19);
if (p1 == p2) {
cout << "p1和p2是相等的";
}
else {
cout << "p1和p2是不相等的";
}
}
int main(void)
{
test();
return 0;
}
函数调用运算符重载
1、函数调用运算符()也可以重载。
2、由于重载后使用的方式非常像函数的调用,因此称为仿函数。
3、仿函数没有固定的写法,非常灵活。
#include <iostream>
#include <string>
using namespace std;
class Myprint {//输出字符串
public:
void operator()(string text) {//重载()运算符,也称作仿函数。
cout << text << endl;
}
};
class Myadd {//两数相加,仿函数非常灵活,没有固定的格式
public:
int operator()(int a, int b) {
return a + b;
}
};
void test()
{
Myprint print;
print("Hello world");
Myadd myadd;
int ret = myadd(10, 20);
cout << "ret = " << ret << endl;
//匿名对象调用
cout << "Myadd()(100,100) = " << Myadd()(100, 100) << endl;
}
int main(void)
{
test();
return 0;
}