运算符重载
运算符重载
让运算符能做一些原来做不了的事情,方便它的使用。
操作数:运算符操作的数字,如1+1,加号操作2个数,为双目运算符
一、运算符重载的概念
//运算符的使用:理解成一个"函数的调用"
1 + 1;
fun(1,1); //加法功能的函数
1、什么是运算符重载:
1、重载,重新载入,就比如之前那讲的函数重载,对一个已有的函数赋值一个新的定义,因此同一个名 字就可以有不同的含义
2、运算符也是可以重载的,比如cout在输出一个变量的时候,能接受不同类型的数据并输出,他就是重 载了<<运算符,这个就是运算符重载
3、所以运算符指的是对已有的运算符重新定义新的运算规则,已适应不同的数据类型,当然重载之后之 前的运算规则还是有的
2、为什么要进行运算符重载
//1 运算符重载之后可以让运算符去适应不同的数据类型,对于基本数据类型,系统给出了运算符的操作规则,对于自定义数据类型来说,系统是不知道该给出什么规则的。
//例如:
class student
{
int id;
int age;
char name[20];
public:
student(int id,int age,cosnt char *name)
{
this->id=id;
this->age=age;
strcpy(this->name,name);
}
}
student stu1(1,23,"李四");
student stu2(2,34,"王五");
stu1+stu2;//如果是这样相加,那么应该加的是什么呢?编译器是不知道,所以编译器就提供了运算符重载这个机制,让用户自定义运算符的运算符规则
二、运算符重载
运算符重载示例:
class CStudent
{
int id;
public:
CStudent(int id)
{
this->id = id;
}
void operator+(const CStudent& stu)
{
cout<< this->id + stu.id << endl;
}
}
CStudent stu1(10);
CStudent stu2(20);
sut1 + stu2; //隐式调用,运算符重载
sut1.operator+(stu2); //显示调用,运算符重载
1、运算符重载类中的定义
//1、关键字:operator,通过关键字来定义运算符重载(跟写个函数一样)
//2、定义:
函数返回值类型 operator 要重载的运算符(参数列表)
{
函数体;
}
//这里我们就把这个运算符的使用,理解为调用函数,只不过和平时的我们用的函数调用不太一样
//示例: 这里我们就用上面的那个student类为示例
//重载+号: 我想让两个对象相加,并返回一个整数
int operator+(const student& stu)
{
//其实我想让两个对象里面的两个年龄相加,并返回他们的和
//这里里面当然也可以写其他的,可以说你想什么功能都可以,返回也自己定
return this->age+stu.age;
}
/*注意:因为我们这个运算符是在类中写的,所以是通过对象调用的,那么this指针会占一个参数,而且是第一个参数,也就是说如果我们重载一个运算符,是在类中,而这个运算符是个单目运算符,那么参数列表
就不用写东西了,是双目,那么就需要传另一个参数进来
*/
绝大部分的运算符重载,都可以参考上面这个+号重载
2、运算符重载的特点
1、运算符重载几乎都是出现在类中或者结构体中
2、几乎所有的运算符都可以被重载, .(成员访问运算符)::(域运算符)?: (条件运算符) sizeof (长度运算符) * (成员指针访问运算符) 这些运算符除外
3、运算符可以理解为函数的一个表现
3、运算符重载的注意事项
1、重载运算符:
这个重载的运算符还是满足原来的规则,不能说重载+,结果做的是-的事,这样会使在 运算符重载的运用上增加很大的难度。
2、运算符重载的参数:
指得就是使用这个运算符所需要的操作数,但是运算符重载通常都是在类中或者是结构体中,所以需要对象来调用这个函数,那么this指针会占一个
3、考虑返回值:
不同的运算符有不同的返回值,要记得满足运算符原来的规则
class CStudent
{
int id;
public:
CStudent(int id)
{
this->id = id;
}
CStudent operator+(const CStudent& stu)
{
CStudent stu3(this->id + stu.id);
return stu3;
}
}
CStudent stu1(10);
CStudent stu2(20);
CStudent stu4 = stu1 + stu2;
4、对于运算符重载的调用:
可以直接使用运算符,也可以通过对象 . 出来调用
4、使用友元函数,实现运算符重载
//对象+对象返回一个整型,也就是返回id的和
class CStudent
{
int id;
public:
friend int operator+(const CStudent& stu1,const CStudent& stu2);
//声明为友元
}
//因为这个是直接访问的私有成员,所以需要在类中声明一句
//但是通常,像这些数据一般都有接口可以访问,那么就可以通过接口访问,就不需要这个friend声明了
int operator+(const CStudent& stu1,const CStudent& stu2)
{
return stu1.id + sut2.id;
}
5、两个不能在类中重载的运算符(左移,右移),和一些运算符重载的示例
class node
{
int val;
char* name;
public:
node(){val=10;}
friend istream& operator>>(istream& is,node& n);//输入
friend ostream& operator<<(ostream& os,node& n);//输出
/*前后++*/
node& operator++()//前++
{
this->val++;
return *this;
}
//后++
node operator++(int)//这里int是占位参,不用传参,只是用来区分前后++的
{
node temp=*this;//保存val的值
this->val++;//val++
return temp;//返回的是没有++的val的值
}
/*=*/
node& operator=(const node& no)
{
//如果之前有内存,就先释放
if(this->name != NULL)
{
delete[] this->name;
this->name = NULL;
}
this->name = new char[strlen(no.name) + 1];
strcpy(this->name,no.name);
return *this;
}
/*伪函数*/
void operator()()
{
cout<<"我是()重载!!"<<endl;
}
};
friend istream& operator>>(istream& is,node& n)//输入
{
is>>n.val;
return is;
}
friend ostream& operator<<(ostream& os,node& n)//输出
{
os<<n.val;
return os;
}
//使用:
node n;
cin>>n;//对对象里面的val赋值
cout<<n;//输出对象里面的val的值
n();//输出 我是()重载!!
智能指针:
class CStudent
{
int id;
public:
CStudent(int id)
{
this->id = id;
}
~CStudent()
{
cout<<"CStudent释放了"<<endl;
}
void getId()
{
cout<<id<<endl;
}
}
/*智能指针:用来托管new出来的对象,让new出来的对象自动释放*/
class CSmartPointer
{
CStudent* pstu; //用来托管的指针
public:
CSmartPointer(CStudent* pstu)
{
this->pstu = pstu;
}
~CSmartPointer()
{
cout<<"智能指针释放了"<<endl;
if(pstu != NULL)
{
delete pstu;
pstu = NULL;
}
}
CStudent* operator->()
{
return pstu;
}
CStudent& operator*()
{
return *pstu;
}
};
//使用
{
CSmartPointer cmp(new CStudent(5));
cmp->getId();
(*cmp).getId();
}