对于内置的数据类,编译器直到如何进行运算
对于自定义数据类型,需要运算符重载
加号运算符重载
class Person
{
public:
int m_A;
int m_B;
//成员函数重载
Person operator+ (Person &p1)
{
Person temp;
temp.m_A = this->m_A + p1.m_A;
temp.m_B = this->m_B + p1.m_B;
return temp;
}
};
Person p3 = p1 + p2;
Person p4 = p1.operator+(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 p3 = p1 + p2;
Person p4 = operator+(p1, p2); //本质
左移运算符重载

//左移运算符重载
class Person
{
friend ostream & operator<<(ostream &cout, Person &p);
private:
int m_A = 10;
int m_B = 20;
// 通常不会利用成员函数 实现左移运算重载,因为无法实现cout在左侧
// 只能利用全局函数重载左移运算符
};
// 只能利用全局函数重载左移运算符
ostream & operator<<(ostream &cout, Person &p)
{
cout << p.m_A << " and " << p.m_B ;
return cout;
//利用链式调用,否则 cout << p1 << endl; 会崩
}
int main()
{
Person p1;
cout << p1 << endl;
system("pause");
return 0;
}
重载左移运算符配合友元可以实现输出自定义的数据类型
只有当要访问类对象的私有成员时才必须使用友元,只访问public成员不使用友元也是可以的。
递增运算符重载
实现自定义数据类型的自增
// 递增运算符重载
class MyInteger
{
friend ostream & operator<<(ostream &cout, MyInteger &myint);
public:
MyInteger()
{
m_Num = 0;
}
// 重载前置++运算符
// 前置递增返回引用
MyInteger & operator++()
{
m_Num++;
return *this;
}
// 重载后置++运算符
// 这个int代表一个占位参数,用于区分前置和后置递增
// 后置递增返回值,因为temp时局部的,不能返回局部变量的引用
MyInteger operator++(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 test()
{
MyInteger myint;
//cout << ++myint << endl;
cout << ++(++myint) << endl;
cout << myint << endl;
cout << "---------"<<endl;
//cout << myint++ << endl;
// 由于重载的后置运算符返回的是值,这里并不能完成对一直对一个数据进行递增操作
cout << myint << endl; // 2
cout << (myint++)++ << endl; // (2++)++ 4
cout << myint << endl; // 3
}
赋值运算符重载
C++编译器至少给一个类添加4个函数
- 默认构造函数
- 默认析构函数
- 默认拷贝构造函数
- 赋值运算符 operator=,对属性进行值拷贝,默认系统的是浅拷贝
class Person
{
public:
Person(int age)
{
m_Age = new int(age); //维护了堆区开辟的数据
}
int *m_Age;
~Person()
{
if (m_Age != NULL)
{
delete m_Age; //这里析构会崩,堆区重复释放
m_Age = NULL;
}
}
};
void test()
{
Person p1(18);
Person p2(20);
p2 = p1; // 浅拷贝
cout << "p1的年龄是: " << *p1.m_Age << endl;
cout << "p2的年龄是: " << *p2.m_Age << endl;
}
// 解决 深拷贝解决浅拷贝问题
// 所以就要重写 赋值运算符
class Person
{
public:
Person(int age)
{
m_Age = new int(age); //维护了堆区开辟的数据
}
int *m_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;
}
};
void test()
{
Person p1(18);
Person p2(20);
Person p3(60);
p3 = p2 = p1; // 浅拷贝
cout << "p1的年龄是: " << *p1.m_Age << endl;
cout << "p2的年龄是: " << *p2.m_Age << endl;
cout << "p3的年龄是: " << *p3.m_Age << endl;
}
关系运算符重载
让两个自动以类型对象进行对比操作
// 关系运算符重载
class Person
{
public:
Person(string name, int age)
{
m_Name = name;
m_Age = age;
}
string m_Name;
int m_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 true;
}
return false;
}
};
void test()
{
Person p1("tom", 15);
Person p2("tom", 11);
if (p1 == p2)
{
cout << "p1 == p2" << endl;
}
if (p1 != p2)
{
cout << "p1 != p2" << endl;
}
}
函数调用运算符重载
函数调用运算符() 也可以重载
重载后称仿函数
仿函数没有固定的写法,非常灵活
class MyPrint
{
public:
//函数重载调用运算符
int operator()(int a,int b)
{
return a + b;
}
};
void test()
{
MyPrint myPrint;
int num = myPrint(1,2); //使用起来非常像函数调用,所以称为仿函数
//仿函数非常灵活,参数功能等依据功能需求自定义,没有固定写法
//匿名函数对象
cout << MyPrint()(12, 12) << endl;
}