c++运算符重载

来源:互联网 发布:淘宝店铺怎样装修视频 编辑:程序博客网 时间:2024/05/17 05:57

运算符重载:运算符重载只是一种”语法上的方便”,也就是它本质只是另一种函数调用的方式

运算符重载和其他函数一样也是一个函数,当编译器遇到适当的模式时,就会调用这个函数

定义重载的运算符就像定义函数,只是该函数的名字是operator@,这里的@代表了被重载的运算符。函数的参数中参数个数取决于两个因素

1运算符是一元(一个参数)的还是二元(两个参数);

2运算符被定义为全局函数(对于一元是一个参数,对于二元是两个参数)还是成员函数(对于一元没有参数,对于二元是一个参数-此时该类的对象用作左耳参数)

代码如下:

#include<iostream>using namespace std;class people{//重载<<运算符friend ostream& operator<<(ostream& os, people& peo){os << peo.age << endl;return os;}public:people(){age = 10;}people(int age){this->age = age;}people(const people& peo){cout << "拷贝构造" << endl;age = peo.age;}//+运算符是两元运算符,在成员函数中重载只需要一元参数,类中本身对象也是一个参数people operator+(people& peo){people tem(peo.age + this->age);return tem;}public:int age;};#if 0//在全局函数重载要两元参数people operator+(people& peo1,people& peo2){people tem(peo1.age+peo2.age);return tem;}#endifvoid test2(){people p1;people p2;people p3 = p1 + p2;//p3=p1.operator+(p2)cout << p3 << endl;}int main(){//test();test2();system("pause");return 0;}
运算符重载成员函数和全局函数结果都一样




前置++和后置++的本质就是运算符重载

//重载前置++和后置++class person{//重载<<运算符friend ostream& operator<<(ostream& os, person& per){os << per.age << endl;return os;}public:person(){age = 10;}//前置++person& operator++(){age++;return *this;}//后置++person operator++(int){person p2;p2.age = this->age;age++;return p2;}public:int age;};void test(){person per;cout << "persn后置++等于" << per++ << endl;//返回的是临时对象,临时对象保存的是原来的值cout << "persn前置++等于" << ++per << endl;//前面前置++对象加了1,在加上1就是2}int main(){test();//test2();system("pause");return 0;}

结果:



注意:从上面可以看出,能用前置++,就用前置++,因为前置++不用创建临时对象,效率高,除非需要后置++的原来的值


重载赋值运算符

赋值运算符重载很容易和拷贝构造函数混淆,在对象还没有初始化构造的时候,=调用的是拷贝构造函数,如果对象初始化后,=调用的是重载赋值运算符函数,默认赋值函数是进行简单的值拷贝(浅拷贝)

#include<iostream>using namespace std;class student{public:student(){this->id = 10;}student(int id){this->id = id;}student(const student& st){cout << "拷贝构造" << endl;this->id = st.id;}public:int id;};void tsteS(){student Stu1(100);student Stu2 = Stu1;//调用拷贝构造函数,Stu2没有初始化构造cout << "Stu2="<<Stu2.id << endl;cout << "----------------------" << endl;student Stu3;Stu3 = Stu1;//这个不调用拷贝构造,因为Stu3已经调用默认构造初始化了,所以调用的是默认赋值运算功能//从结果可以看出默认赋值功能是进行简单的值拷贝,如果有指针的话就得重载赋值运算符的功能了cout << "Stu3="<<Stu3.id << endl;}int main(){tsteS();system("pause");return 0;}

结果如图:Stu3=Stu1并没有调用拷贝构造



赋值运算符的深拷贝

#define _CRT_SECURE_NO_WARNINGS#include<iostream>using namespace std;//如果类的内部有指针,并且指针指向堆上的内存。//默认把析构函数 赋值函数 拷贝构造函数都写上。class Point{public:Point(const char* name){this->name = new char[strlen(name) + 1];strcpy(this->name, name);}Point(const Point& p){this->name = new char[strlen(p.name) + 1];strcpy(this->name, name);}//一定要返回引用类型,不然实现连续赋值的时候产生新的对象,赋值错误Point& operator=(const Point& p){//这个时候当前对象已经创建了,name已经指向了堆内存,直接赋值的话会导致堆内存没有及时释放//释放原来的内存if (name != NULL){delete[] name;this->name = NULL;}//开辟新的内存this->name = new char[strlen(p.name) + 1];strcpy(this->name, p.name);return *this;}~Point(){if (name != NULL){delete[] name;this->name = NULL;}}public:char* name;};int main(){Point p1("make");Point p2("peter");Point p3("joke");//(p3= p2) = p1;//如果不是返回值引用的话,p3就是p2的值,p3=p2产生新的对象,p1就给新的对象赋值了,没有赋值给p3,新的对象调用拷贝构造p3 = p2 = p1;//如果不是引用的话,p2=p1产生新的对象,新的对象调用默认构造,赋值给p3就会出现值未知乱码cout << p1.name << endl;cout << p2.name << endl;cout << p3.name << endl;system("pause");return 0;}
如果赋值运算符函数返回值不是引用的话结果如下:



如果赋值运算符函数返回值是引用的话结果如下:



注意:除了赋值号(=)外,基类中被重载的操作符都将被派生类继承。

原创粉丝点击