类与对象_运算符重载
运算符重载概念:对已有的运算符重新进行定义,赋予另一种功能,以适应不同的数据类型
加号运算符重载
作用:实现两个自定义数据类型相加的运算
#include <iostream> using namespace std; //成员函数重载 class Person { public: 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; }; //全局函数重载 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; } int main() { Person p1; p1.m_A = 10; p1.m_B = 10; Person p2; p2.m_A = 10; p2.m_B = 10; Person p3 = p1 + p2; cout << p3.m_A << " " << p3.m_B << endl; // 20 20 Person p4 = p1 - p2; cout << p4.m_A << " " << p4.m_B << endl; // 0 0 }
运算符重载也可以发生函数重载
总结1:对于内置的数据类型的表达式的运算符是不可能改变的
总结2:不要滥用运算符重载
左移运算符重载
作用:可以输出自定义数据类型
#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: //operator<<(cout) 相当于 p.operator<<(cout) 简化为 p << cout; // 顺序不是 cout << p;这样的预期效果,所以一般不用成员函数重载 int m_A; int m_B; }; //流对象不能复制,只能引用&cout ostream & operator<<(ostream &cout, Person &p) { //本质 operator(cout, p) 简化 cout << p; cout << "m_A = " << p.m_A << " " << "m_B = " << p.m_B; return cout; //链式编程思想 可以在后面接endl了 } int main() { Person p(10, 10); //以前的<<功能不变,追加了输出Person对象的功能 cout << p << endl; }
总结:重载做运算符配合友元可以实现输出自定义数据类型
递增运算符重载
作用:通过重载递增运算符,实现自己的整型数据


#include <iostream> using namespace std; class MyInteger { friend ostream & operator<<(ostream &cout, MyInteger myint); public: MyInteger() { m_Num = 0; } //重载前置++运算符 MyInteger& operator++() { //返回引用 是为了一直对一个数据进行递增操作 //先自增 m_Num++; //后返回 return *this; } //重载后置++运算符 MyInteger operator++(int) { //int代表占位参数,可以用于区分前置递增和后置递增 //先记录当时结果 MyInteger temp = *this; //后 递增 m_Num++; //最后将记录结果返回 return temp; //temp是局部对象,不要返回引用 } private: int m_Num; }; //重载左移运算符 ostream & operator<<(ostream &cout, MyInteger myint) { cout << myint.m_Num; return cout; } int main() { MyInteger myint; cout << myint << endl; //0 cout << ++myint << endl;//1 cout << myint++ << endl;//1 cout << myint << endl;//2 }
总结:前置递增返回引用,后置递增返回值
赋值运算符重载
C++编译器至少给一个类添加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; }; int main() { Person p1(18); Person p2(20); Person p3(30); p3 = p2 = p1; cout << *p1.m_Age << endl; //18 cout << *p2.m_Age << endl; //18 cout << *p3.m_Age << endl; //18 }
关系运算符重载
作用:重载关系运算符,可以让两个自定义类型对象进行操作对比
#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; }; int main() { Person p1("Tom", 18); Person p2("Tom", 18); if (p1 == p2) { cout << "p1和P2相等" << endl; } else cout << "p1和P2不相等" << endl; }
函数调用运算符重载
- 函数调用运算符()也可以重载
- 由于重载后使用的方式非常像函数的调用,因此称为仿函数
- 仿函数没有固定写法,非常灵活#include <iostream>
#include <string> using namespace std; class MyPrint { public: void operator()(string test) { cout << test << endl; } }; class MyAdd { public: int operator()(int num1, int num2) { return num1 + num2; } }; int main() { MyPrint myPrint; myPrint("hello world"); MyAdd myAdd; cout << myAdd(1, 1) << endl;
cout << MyAdd()(100, 100) << endl; //匿名函数对象 }

浙公网安备 33010602011771号