C++预定义中的运算符只能对基本的内置数据类型进行操作,但是对于我们自定义的类型是没有办法操作的,我们对这么运算符重新定义,才能对我们自己定义的数据类型进行操作。
对于运算符重载,它的实质其实是函数重载或者说,函数多态。重载的运算符是带有特殊名称的函数,函数名是由关键字 operator
和其后要重载的运算符符号构成的。运算符重载函数的格式:
<返回类型说明符> operator <运算符符号>(<参数表>) { <函数体> }
+ 运算符重载
+号运算符重载的作用就是实现两个自定义数据类型相加的运算
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
Student() {}
Student(int a, int b)
{
m_A = a;
m_B = b;
}
Student operator+(const Student &s)
{
Student temp;
temp.m_A = this->m_A + s.m_A;
temp.m_B = this->m_B + s.m_B;
return temp;
}
public:
int m_A;
int m_B;
};
//全局函数实现 + 号运算符重载
//Student operator+(const Student &s1, const Student &s2)
//{
// Student temp;
// temp.m_A = s1.m_A + s2.m_A;
// temp.m_B = s1.m_B + s2.m_B;
// return temp;
//}
void test01()
{
Student s1(10, 10);
Student s2(20, 20);
Student s3 = s1 + s2;
cout << "m_A = " << s3.m_A << "\nm_B = " << s3.m_B << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
<< 左移运算符重载
我们之前是这样使用左移运算符的
int a = 10;
cout << a;
现在我们有一个叫s的Student的类,类当中有年龄,班级,我们想这样使用cout
cout << s
就可以直接将类当中的学号,年龄,班级全部输出。
class Student
{
friend ostream& operator<<(ostream& cout, Student& s);
public:
Student(int id, int age, int Class)
{
this->m_Id = id;
this->m_Age = age;
this->m_Class = Class;
}
//成员函数 实现不了
//void operator<<(Person& p){
//}
private:
int m_Id;
int m_Age;
int m_Class;
};
//全局函数实现左移重载
//cout的类型为ostream,对象只能有一个
//返回cout的目的是为了链式编程,所以这里的返回类型我们是ostream而且是以引用方式
//当然也可以是void,但是如果返回的是void,那么下面的cout << s之后就不能追加后面的"hello!",
//因为返回的是void,而想要追加内容,我们返回的必须是cout才行。
ostream& operator<<(ostream& cout, Student& s) {
cout << "id:" << s.m_Id << " age:" << s.m_Age << "class:" << s.m_Class;
return cout;
}
void test01() {
Student s(001, 10, 2020001);
cout << s << "hello!" << endl; //链式编程
}
int main() {
test01();
system("pause");
return 0;
}
++(–)运算符重载
作用是可以输出自定义数据类型
下面代码展示的是++运算符重载,当然–也是同理
class Integer
{
//我们先要重载一下左移运算符
friend ostream& operator<<(ostream& out, MyInteger myint);
public:
Integer() {
m_Num = 0;
}
//前置++ 先++ 再返回
Integer& operator++() {
m_Num++;
return *this;
}
//后置++ 先返回 再++
Integer operator++(int) {
Integer temp = *this; //记录当前本身的值,然后让本身的值加1,但是返回的是以前的值,达到先返回后++;
m_Num++;
return temp;
}
private:
int m_Num;
};
ostream& operator<<(ostream& out, Integer myint) {
out << myint.m_Num;
return out;
}
//前置++ 先++ 再返回
void test01() {
Integer myInt;
cout << ++myInt << endl;
cout << myInt << endl;
}
//后置++ 先返回 再++
void test02() {
Integer myInt;
cout << myInt++ << endl;
cout << myInt << endl;
}
int main() {
test01();
test02();
system("pause");
return 0;
}
==运算符重载
让两个自定义类型进行比较
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
};
bool operator==(Person & p)
{
if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
return true;
} else {
return false;
}
}
bool operator!=(Person & p)
{
if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
return false;
} else {
return true;
}
}
string m_Name;
int m_Age;
};
void test01()
{
//int a = 0;
//int b = 0;
Person p1("张三", 18);
Person p2("张三", 18);
if (p1 == p2) {
cout << "p1和p2相等" << endl;
} else {
cout << "p1和p2不相等" << endl;
}
if (p1 != p2)
{
cout << "a和b不相等" << endl;
} else {
cout << "p1和p2相等" << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
函数调用运算符重载
函数调用运算符()也可以重载,由于其长得很像函数,故称之为仿函数
class MyAdd
{
public:
int operator()(int a, int b)
{
return a + b;
}
};
void test01()
{
MyAdd add;
int ret = add(10, 10);
cout << "ret = " << ret << endl;
//匿名对象调用
cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl;
}
int main() {
test02();
system("pause");
return 0;
}
赋值运算符重载
我们知道,编辑器会给一个类至少添加4个函数,分别是
- 默认无参构造函数
- 默认析构函数
- 默认拷贝构造函数
- 赋值运算符 operator=
若类中有属性指向堆区,做赋值操作时会出现深浅拷贝问题
class Person
{
public:
Person(int age)
{
//将年龄数据开辟到堆区
m_Age = new int(age);
}
//重载赋值运算符
Person& operator=(Person &p)
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
//编译器提供的代码是浅拷贝
//提供深拷贝重新new一块区域来操作m_Age 解决浅拷贝的问题
m_Age = new int(*p.m_Age);
//返回自身
return *this;
}
~Person()
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}
int *m_Age;
};
void test01()
{
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()
{
test01();
system("pause");
return 0;
}