运算重载符
概念: 运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数原型:
返回值 operator操作符(参数列表)
注意:
- 运算符重载,就是对已有的运算符重新进行定义,赋予其另外一种功能,以适应不同的数据类型
- 不能通过重载操作符来创建新的操作符,如operator@
- 必须含有一个类类型或枚举类型的操作数
- 不能改变内置类型的含义
- 重载函数如果写成成员函数,左侧第一个参数隐含了一个Date* const this的形参,限定为第一个形参
- 重载函数如果写成全局,那么左边是你输入的第一个参数,右边是第二个参数
- .*,::,?:,sizeof,.这五个运算符不能重载
注意以下几点:
- 除了赋值号(=)之外,基类中被重载的操作符都将被派生类继承
- =,[],(),->操作符只能通过成员函数进行重载
- << 和 >> 操作符最好通过友元进行重载
- 不要重载&&和||运算符,因为无法实现短路规则
选择作为成员或非成员
当我们定义重载的运算符时,必须首先决定是将其声明为类的成员函数还是声明为一个普通的非成员函数。在某些时候我们别无选择,因为有的运算符必须作为成员;另一些情况下,运算符作为普通函数比作为成员更好。
下面的准则有利于我们在运算符定义为成员函数还是普通的非成员函数做出抉择:
- 赋值(=)、下标([ ])、调用(())和成员访问箭头)(->),运算符必须是成员
- 复合运算符一般来说是成员,但是非必须
- 改变成员状态的运算符或者给定类型密切相关的运算符,比如递增、递减和解引用运算符,通常应该是成员
- 具有对称性的运算符可能转换任意一端的运算对象,例如算术、相等性、关系和位运算符等,因此他们通常应该是普通的非成员对象
赋值运算符重载
我们可以重载赋值运算符,无论形参的类型是什么,赋值运算符都必须定义为成员函数
赋值运算符,赋值之后,左侧运算对象和右侧运算对象的值相等,并且运算应该返回它左侧运算对象的一个引用
特性:
- 返回是*this
- 如果没有显示定义,编译器也会生成一个,按字节序拷贝
Date& operator=(const Date& d)
{
// 检测是否自己给自己赋值
if (this == &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
实例:
#define _CRT_SECURE_NO_WARNINGS #include<iostream> //引入头文件 #include<string>//C++中的字符串 using namespace std; //标准命名空间 class Maker { public: Maker() { id = 0; age = 0; } Maker(int id, int age) { this->id = id; this->age = age; } public: int id; int age; }; void test01() { Maker m1(10, 20); Maker m2; m2 = m1; //默认的赋值运算符重载函数进行了简单的赋值操作 //就类似于字节序的浅拷贝 cout << m2.age << m2.id << endl; } class Student { public: Student(const char * name) { pName = new char[strlen(name)+1]; strcpy(pName, name); } //防止浅拷贝 Student(const Student& stu) { pName = new char[strlen(stu.pName) + 1]; strcpy(pName, stu.pName); } //重写赋值运算符重载函数 //为什么要返回引用 Student& operator =(const Student& stu)//第一个参数默认是this指针 { //1.不能确定this指向的空间是否能装下stu中的数据,所以先释放this指向的空间 if (this->pName!= NULL) { delete[] this->pName; this->pName = NULL; } //2.释放了之后再来申请堆区空间,大小由stu决定 this->pName = new char[(strlen(stu.pName) + 1)]; //3.拷贝函数 strcpy(this->pName, stu.pName); //返回对象本身 return *this;//this中存放的是对象的地址,对地址取*表示对象本身 } void printfStudent() { cout << this->pName << endl; } ~Student() { delete[] pName; pName = NULL; } public: char* pName ; }; void test02() { Student s1("悟空"); Student s2("唐僧"); Student s3("八戒"); s1 = s2 = s3; s1.printfStudent(); s2.printfStudent(); s3.printfStudent(); cout << &(s2 = s3) << endl; cout << &s2 << endl; } int main() { test01(); cout << "-------------------------------" << endl; test02(); system("pause"); return EXIT_SUCCESS;
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/293245.html