数声风笛离亭晚,君向潇湘我向秦。
运算符重载
由于运算符只能实现一些内置数据类型的运算,而无法对自定义数据类型进行运算,对目前已有的运算符进行重新定义,以拓展其功能。
加法运算符重载
加法运算符重载有全局函数和局部函数两种实现方式,下面的代码重新编写了加法运算符函数重载加法运算符,将两个自定义类Person的的两个属性number1,number2相加,返回属性相加后的Person类。
函数名称使用编译器通用名称operator+命名重载加法运算符函数,可以将函数调用(p1.operator(p1)和p1.operator(p1.p2))简化为p1+p2的形式。
//局部函数实现+运算符重载
#include <iostream>
using namespace std;
class Person
{
public:
int number1;
int number2;
Person operator+(const Person& p)
{
Person temp;
temp.number1 = this->number1 + p.number1;
temp.number2 = this->number2 + p.number2;
return temp;
}
};
void printPerson(Person p1)
{
cout << "数值1为" << p1.number1 << endl;
cout << "数值2为" << p1.number2 << endl;
}
int main()
{
Person p1;
p1.number1 = 10;
p1.number2 = 20;
Person p2;
p2.number1 = 10;
p2.number2 = 20;
Person p3 = p1 + p2;//相当于p1.operaor+(p2)
printPerson(p3);
system("pause");
return 0;
}
//全局函数实现+运算符重载
#include <iostream>
using namespace std;
class Person
{
public:
Person(int a, int b) :number1(a), number2(b) {};//初始化列表
public:
int number1;
int number2;
};
Person operator+(Person& p1, Person& p2)
{
Person p3(0,0);
p3.number1 = p1.number1 + p2.number1;
p3.number2= p1.number2 + p2.number2;
return p3;
}
void printPerson(Person p1)
{
cout << "数值1为" << p1.number1 << endl;
cout << "数值2为" << p1.number2 << endl;
}
int main()
{
Person p1(10, 20);
Person p2(10, 20);
Person p3 = p1 + p2;//p1.operaor+(p1,p2)
printPerson(p3);
}
左移运算符重载
重载左移运算符,cout<<加自定义类Person,可以打印Person的属性。
这里只能使用全局函数重载,是因为如果使用局部函数重载,只能实现<<cout效果,而不能实现cout<<。
#include <iostream>
using namespace std;
class Person
{
public:
int number1;
int number2;
Person(int a, int b) : number1(a), number2(b) {};//初始化列表
};
//输出流对象cout只能有一个,所以传参跟返回值都需要使用引用
//全局函数重载左移运算符
ostream & operator<<(ostream & out, Person & p)
{
cout << "number1=" << p.number1 << endl;
cout << "number2=" << p.number2 << endl;
return out;
}
void test()
{
Person p1(10, 20);
cout << p1 << endl;//使用了链式编程的思想,即同一个对象上通过多个方法的调用链实现一系列操作,根据其后参数的不同,前一个<<使用重载<<的定义,后一个<<使用原有的定义。
}
int main()
{
test();
system("pause");
return 0;
}
递增运算符重载
重载递增运算符,自定义类Person++,++Person,可以实现类属性的递加。
#include <iostream>
using namespace std;
class Person
{
public:
int number1 = 0;
//前置++返回值为对象,由于是在类内的局部函数,对类内属性进行++,所以不需要传入其他参数
Person& operator++()
{
number1++;
return *this;
}
//后置++返回值为数值,同一作用域下返回值不同不满足函数重载的条件,所以通过前置占位参数int来区分重载前置++和后置++函数,此处只能用int
//只要在重载操作符的参数中加上一个整数型参数,编译器就会自动将这个函数标示为后置,相应的不加则是前置
int operator++(int)
{
int temp = number1;
number1++;
return temp;
}
};
ostream & operator<<(ostream & out, Person & p)
{
cout <<p.number1;
return out;
}
void test1()
{
Person p1;
cout << p1++ << endl;
cout << p1 << endl;
}
void test2()
{
Person p1;
cout << ++p1 << endl;
cout << p1 << endl;
}
int main()
{
test1();
test2();
system("pause");
return 0;
}
赋值运算符重载
编译器提供的赋值运算符是浅拷贝,如果使用编译器提供的赋值运算符对两个自定义的类Person进行赋值运算p1=p2时,如果自定义对象有在堆区申请内存,则会导致堆区内存重复释放的问题。
重载赋值运算符,通过深拷贝来解决该问题。
#include <iostream>
using namespace std;
class Person
{
public:
Person(int age)
{
m_age = new int(age);
}
int* m_age;
//返回引用是为了处理a=b=c的情况
Person& operator=(Person& p)
{
//判断age是否为空,如果不为空,删除堆区申请的空间,并赋为空指针
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
}
//深拷贝,在堆区申请一块位置,并将传入的*p.m_age的值赋给它,同时另m_age指针等于它
m_age = new int(*p.m_age);
return *this;//返回自身
}
~Person()
{
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
}
}
};
void test()
{
Person p1(12);
Person p2(13);
Person p3(14);
p1 = p2 = p3;//将p3的值赋给p2,再将p2的值赋给p1;
cout << *p1.m_age << endl;
cout << *p2.m_age << endl;
cout << *p3.m_age << endl;
}
int main()
{
test();
system("pause");
return 0;
}
关系运算符
重载关系运算符!=、==,比较两个Person类的属性是否相等。
#include <iostream>
using namespace std;
class Person
{
public:
int m_number1;
int m_number2;
Person(int number1, int number2) :m_number1(number1), m_number2(number1) {};
};
bool operator!=(Person p1, Person p2)
{
if (p1.m_number1 == p2.m_number1 && p1.m_number2 == p2.m_number2)
{
return false;
}
else
{
return true;
}
}
bool operator==(Person p1, Person p2)
{
if (p1.m_number1 == p2.m_number1 && p1.m_number2 == p2.m_number2)
{
return true;
}
else
{
return false;
}
}
void test()
{
Person p1(11, 12);
Person p2(12, 13);
Person p3(11, 12);
if (p1 != p2)
{
cout << "p1不等于p2" << endl;
}
else
{
cout << "p1等于p2" << endl;
}
if (p1 == p3)
{
cout << "p1等于p3" << endl;
}
else
{
cout << "p1不等于p3" << endl;
}
}
int main()
{
test();
system("pause");
return 0;
}
函数调用运算符重载
函数调用运算符重载后的使用方式与函数调用相似,因此也被称为仿函数,仿函数十分灵活,参数数量、返回值类型都不固定,根据需求决定。
#include <iostream>
using namespace std;
class Person
{
public:
int operator()(int number1,int number2)
{
return number1 + number2;
}
};
void test()
{
Person p1;
int ret = p1(100, 200);
cout<< ret<<endl;
}
int main()
{
test();
//匿名函数对象,不创建对象而通过匿名对象调用仿函数。Person()为匿名对象,当前行结束立即被释放。
int ret1=Person()(100, 200);
cout << ret1 << endl;
system("pause");
return 0;
}