运算符重载
:对已有的运算符进行重新定义,赋予其另一种功能,以适应不同的数据类型。
加号运算符重载
加号运算符重载
:实现两个自定义数据类型的相加操作。
#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+(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 p,int num) {
Person temp;
temp.m_a = p.m_a + num;
temp.m_b = p.m_b + num;
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.operator+(p2);
//全局函数调用本质
//Person p3 = p1.operator+(p1,p2);
Person p3 = p1 + p2;
cout <<"p3的值a为" <<p3.m_a << " p3的值b为" << p3.m_b << endl;
Person p4 = p1 + 100;
cout << "p4的值a为" << p4.m_a << " p4的值b为" << p4.m_b << endl;
}
int main() {
test01();
system("pause");
return 0;
}
左移运算符重载
左移运算符重载
:可以输出自定义数据类型。
#include<iostream>
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:
/*利用成员函数重载左移运算符 p.operator<<(cout) 简化版本p<<cout
不能利用成员函数重载左移运算符,因为这样无法实现cout在左侧
void operator<<(cout) {
}*/
int m_a;
int m_b;
};
//只能利用全局函数重载左移运算符
//cout全局只能有一个,所以必须用引用的方式传进来,不能创建出来新的一个
ostream & operator<<(ostream &cout,Person &p) { //本质是operator<<(cout,Person p) 简化版本cout<<p
cout <<"输出a"<< p.m_a <<"输出b" <<p.m_b << endl;
return cout;
}
void test01() {
Person p(10,10);
/*p.m_a = 20;
p.m_b = 10;*/
cout << p<<endl; //链式编程思想
}
int main() {
test01();
system("pause");
return 0;
}
递增运算符重载
递增运算符重载
:实现对自定义数据类型的递增操作。
#include<iostream>
using namespace std;
//自定义整型类
class Integer {
friend ostream& operator<<(ostream& cout, Integer myint); //全局函数做友元
public:
Integer() {
m_number = 0;
}
//重载前置++运算符 返回引用是为了一直对一个数据进行递增操作
Integer& operator++() {
//先进行++运算
m_number++;
//再将自身做返回
return *this;
}
//重置后置++运算符 这里的参数int代表占位参数,区分函数重载
//区分前置后置用占位参数int就可以区分了
//后置递增一定要返回的是值
Integer operator++(int) { //前置递增返回的是引用,后置递增返回的是值!!!!!!!!!!!!!!!!!
//先记录当前结果
Integer temp = *this; //temp是一个局部对象,当前函数执行完temp就被释放掉了,如果引用只能引用一次,再引用第二次就是非法操作
//再进行递增操作
m_number++;
//最后将记录结果作返回
return temp;
}
private:
int m_number;
};
//重载左移运算符
ostream &operator<<(ostream &cout,Integer myint) {
cout << myint.m_number << endl;
return cout;
}
void test01() { //++a操作 前置递增
Integer myint;
cout << ++(++myint)<<endl;
cout << myint << endl;
}
void test02() { //a++操作 后置递增
Integer myint;
cout << myint++ << endl;
cout << myint<<endl;
}
int main() {
test01();
test02();
//内置数据类型会一直对同一个数据进行操作,但是++(++myint)相当于加完一次就成为了一个新数据,因此需要引用返回来保证一直对一个数据进行操作
/*int a = 0;
cout << a++ << endl;
cout << a << endl; */
system("pause");
return 0;
}
递减运算符重载
递减运算符重载
:实现对自定义数据类型的递减操作。
#include<iostream>
using namespace std;
class Myinteger {
friend ostream& operator<<(ostream& cout, Myinteger myint);//左移运算符函数做友元,访问私有属性
public:
Myinteger() {
m_number = 10;
}
//重载前置递减运算符
Myinteger &operator--() {
//先递减
m_number--;
//再返回结果
return *this;
}
//重载后置递增运算符
Myinteger operator--(int) { //int做占位参数来区分函数重载
//先返回当前值
Myinteger temp = *this;
//再进行递减操作
m_number--;
//最后将记录的结果返回
return temp;
}
private:
int m_number;
};
//重载左移运算符
ostream& operator<<(ostream & cout,Myinteger myint) {
cout << myint.m_number << endl;
return cout;
}
void test01() { //前置递减 --a操作
Myinteger myint;
cout << --myint << endl;
cout << myint << endl;
}
void test02() { //后置递减 a--操作
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>
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 test01() {
Person p1(18);
Person p2(20);
Person p3(21);
//返回对象本身进行一个链式编程来进行赋值操作
p3 = p2 = p1;//赋值操作
cout << "p1的年龄为 " << *p1.m_age << endl; //加上指针对数据进行*解引用,不然会显示一串存储地址
cout << "p2的年龄为 " << *p2.m_age << endl;
cout << "p3的年龄为 " << *p3.m_age << endl;
}
int main() {
test01();
//int a = 10;
//int b = 10;
//int c = 10;
//c = b = a; //内置数据类型允许这种连等的操作
//cout << a << b << c<<endl;
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;
}
//重载关系运算符!=号
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("Amy",18);
Person p2("Amy",18);
if (p1 == p2) {
cout << "p1和p2是相等的" << endl;
}
else {
cout << "p1和p2是不相等的" << endl;
}
}
void test02() {
Person p3("Tom", 18);
Person p4("Jeery", 18);
if (p3 != p4) {
cout << "p3和p4是不相等的" << endl;
}
else {
cout << "p3和p4是相等的" << endl;
}
}
int main() {
test01();
test02();
system("pause");
return 0;
}
函数调用运算符重载
函数调用运算符重载
:由于重载后使用的方式非常像函数的调用,因此称为仿函数。仿函数没有固定写法,非常灵活。
匿名函数对象
:类型加小括号创建匿名对象,使用完系统直接释放。
#include<iostream>
#include<string>
using namespace std;
class Myprint {
public:
//函数调用()运算符重载
void operator()(string text) {
cout << text << endl;
}
};
void test01() {
Myprint myprint;
myprint("hello world!"); //由于使用起来非常类似函数调用,因此称为仿函数
}
void test02(string text) {
cout <<"test02的函数调用 "<< text << endl;
}
//仿函数非常灵活,没有一个固定的写法
//加法类
class Myadd {
public:
int operator()(int a,int b) {
return a + b;
}
};
void test03() {
Myadd myadd;
int result = myadd(100, 100);
cout <<"result = "<< result << endl;
//匿名函数对象
cout << Myadd()(100, 100) << endl;
}
int main() {
test01();
test02("hello world!");
test03();
system("pause");
return 0;
}