重载加减运算符
成员函数进行运算符重载

{this->m_A = a;this->m_B = b;}//成员函数实现 + 号运算符重载Person operator+(const Person& p) {Person temp;temp.m_A = this->m_A + p.m_A;temp.m_B = this->m_B + p.m_B;return temp;}public:int m_A;int m_B;};//全局函数实现 + 号运算符重载//Person operator+(const Person& p1, const Person& p2) {// Person temp(0, 0);// temp.m_A = p1.m_A + p2.m_A;// temp.m_B = p1.m_B + p2.m_B;// return temp;//}//运算符重载 可以发生函数重载Person operator+(const Person& p2, int val){Person temp;temp.m_A = p2.m_A + val;temp.m_B = p2.m_B + val;return temp;}void test() {Person p1(10, 10);Person p2(20, 20);//成员函数方式Person p3 = p2 + p1; //相当于 p2.operaor+(p1)cout << "mA:" << p3.m_A << " mB:" << p3.m_B << endl;Person p4 = p3 + 10; //相当于 operator+(p3,10)cout << "mA:" << p4.m_A << " mB:" << p4.m_B << endl;}int main() {test();system("pause");return 0;}
总结1:对于内置的数据类型的表达式的的运算符是不可能改变的 总结2:不要滥用运算符重载
未使用重载进行计算
class Person {public:Person(int v1, int v2) {m_v1 = v1;m_v2 = v2;}int m_v1;int m_v2;Person add(Person& p) {Person temp;temp.m_v1 = this->m_v1 + p.m_v1;temp.m_v2 = this->m_v2 + p.m_v2;return temp;}};void Example() {Person p1(10,20);Person p2(30,40);p2 = p2.add(p1);cout << "P2.M_V1 = " << p2.m_v1 << endl;cout << "P2.M_V2 =" << p2.m_v2 << endl;}//实际上是一个浅拷贝
使用重载运算符
#include <iostream>#include <cstdio>#include <malloc.h>using namespace std;class Person {public:Person():m_v1(0),m_v2(0) {}Person(int v1, int v2) {m_v1 = v1;m_v2 = v2;}int m_v1;int m_v2;Person operator+ (Person& p) {Person temp;temp.m_v1 = this->m_v1 + p.m_v1;temp.m_v2 = this->m_v2 + p.m_v2;return temp;}};void Example() {Person p1(10,20);Person p2(30,40);Person p3= p2 + p1;cout << "P2.M_V1 = " << p3.m_v1 << endl;cout << "P2.M_V2 =" << p3.m_v2 << endl;}int main() {Example();return 0;}
全局重载需要两个引用
#include <iostream>#include <cstdio>#include <malloc.h>using namespace std;class Person {public:Person():m_v1(0),m_v2(0) {}Person(int v1, int v2) {m_v1 = v1;m_v2 = v2;}int m_v1;int m_v2;};Person operator+(Person& p1, Person& p2) {Person temp;temp.m_v1 = p1.m_v1 + p2.m_v1;temp.m_v2 = p1.m_v2 + p2.m_v2;return temp;}void Example() {Person p1(10,20);Person p2(30,40);Person p3= p2 + p1;cout << "P2.M_V1 = " << p3.m_v1 << endl;cout << "P2.M_V2 =" << p3.m_v2 << endl;}int main() {Example();return 0;}
重载左移运算符
一般来说不使用成员函数来重载左移运算符,因为cout在左移运算符的左边,如果重载,对象只能在右边。
所以使用全局函数来重载左移运算符。
class Person {public:Person(int a,int b) {this->m_a = a;this->m_b = b;}int m_a;int m_b;};void operator<<(ostream& cout, Person& p) {cout << "m_a = " << p.m_a << " m_b = " << p.m_b;}void Example() {Person p(1, 2);cout << p;}
全局函数重载可解决问题,但是返回值是void,后面无法加入endl;
返回值改为原有的对象,也就是cout,就可以解决问题,加入return cout
ostream& operator<<(ostream& cout, Person& p) {cout << "m_a = " << p.m_a << " m_b = " << p.m_b;return cout;}void Example() {Person p(1, 2);cout << p << endl;}
问题即可解决。
在实际编程规范中,成员变量一般为私有的,那全局重载就需要将全局函数变为友元
class Person {friend ostream& operator<<(ostream& cout, Person& p);public:Person(int a,int b) {this->m_a = a;this->m_b = b;}private:int m_a;int m_b;};ostream& operator<<(ostream& cout, Person& p) {cout << "m_a = " << p.m_a << " m_b = " << p.m_b;return cout;}
总结:重载左移运算符配合友元可以实现输出自定义数据类型
重载自增运算符
前置自增
class myInt {friend ostream& operator<<(ostream& cout, myInt& in);public:myInt() {m_int = 0;}//返回引用是为了一直对同一个对象进行递增,否则将会返回新的对象myInt& operator++() {m_int++;return *this;}private:int m_int;};ostream& operator<<(ostream& cout, myInt& in) {cout << in.m_int;return cout;}void Example() {myInt myint;cout << myint << endl;}
后置自增
void operator++(int) {//int 是一个占位参数,可以用于区分前置运算符和后置运算符//先记录初始结果//再进行递增运算//然后再返回最后结果}
myInt operator++(int) {//int 是一个占位参数,可以用于区分前置运算符和后置运算符myInt temp;temp = *this;this->m_int++;return temp;}
class MyInteger {friend ostream& operator<<(ostream& out, MyInteger myint);public:MyInteger() {m_Num = 0;}//前置++MyInteger& operator++() {//先++m_Num++;//再返回return *this;}//后置++MyInteger operator++(int) {//先返回MyInteger temp = *this; //记录当前本身的值,然后让本身的值加1,但是返回的是以前的值,达到先返回后++;m_Num++;return temp;}private:int m_Num;};ostream& operator<<(ostream& out, MyInteger myint) {out << myint.m_Num;return out;}//前置++ 先++ 再返回void test01() {MyInteger myInt;cout << ++myInt << endl;cout << myInt << endl;}//后置++ 先返回 再++void test02() {MyInteger myInt;cout << myInt++ << endl;cout << myInt << endl;}int main() {test01();//test02();system("pause");return 0;}
重载赋值运算符
再深浅拷贝中提到的下列问题可通过自己设计深拷贝解决:
class Person {public:Person(int a) {m_age = new int(a);}~Person() {if (m_age != NULL) {delete m_age;}}Person(const Person& p) {m_age = new int(*p.m_age);}int *m_age;};void example() {Person p1(18);Person p2(p1);cout << *p2.m_age << endl;}
但若表达式为赋值而非传参,则需要对赋值运算符进行重载
#include <iostream>#include <string>using namespace std;class Person {public:Person(int a) {m_age = new int(a);}~Person() {if (m_age != NULL) {delete m_age;}}Person& operator=(Person &p) {//如果堆区存在数据,则需要先进行delete清理if (this->m_age != NULL) {delete m_age;}this->m_age = new int(*p.m_age);//然后再进行深拷贝//要想连等成功,必须要返回一个对象//左值右值的类型相同return *this;//返回自身可以实现类型相同//this类型是Person引用}//Person(const Person& p) {// m_age = new int(*p.m_age);//}int *m_age;};void example() {Person p1(18);Person p2(20);Person p3(30);p1 = p2 = p3;cout << *p1.m_age << endl;cout << *p2.m_age << endl;cout << *p3.m_age << endl;}int main() {example();return 0;}
重载关系运算符
#include <iostream>#include <string>using namespace std;class Person {public:Person(string str,int age) {this->age = age;name = str;}bool operator==(const Person& p) {if (p.age == this->age && this->name == p.name) {return true;}else return false;}bool operator!=(const Person& p) {if(p.age != this->age || this->name != p.name) {return true;}else return false;}string name;int age;};void example() {Person p1("zhang", 18);Person p2("zhang", 18);Person p3("li", 20);if (p1 != p3) {cout << "Reconstruct Complete";}}int main() {example();return 0;}
重载函数调用运算符
仿函数
#include <iostream>#include <string>using namespace std;class Person {public:void operator()(string str) {cout << str << endl;}};void example() {Person print;print("Hello World!");//由于使用起来非常像函数,所以称为仿函数}int main() {example();return 0;}
仿函数非常灵活,不限于写法
