概念以及语法
运算符重载:operator
函数原型:返回值类型 operator 操作符(参数列表)
//操作符有几个操作数就有几个参数
//操作符只包含C/C++已经有的,就是说我们不能创建新的操作符,只能重载已有的运算符
例如使用operator来重载@,.等运算符,因为C/C++本身没有这个运算符
必须有一个自定义类型的参数
这个很好理解,假如没有自定义类型,那就没有必要重载运算符了
原有的操作符就能解决,这也是运算符重载的来由,例如一般数字加减乘除我们可以使用+-*/,但是假如我们要对两个日期进行加减呢?原有的运算符体系久无法解决,这就需要我们自己写一个,这就是运算符重载
深入理解:
不能重载运算符去改变内置类型
什么意思?
例如要对+加号重载,但是你不能把这个原本是处理加法的符号,改成减法的
在类成员时,形式上只有一个参数,那是因为有一个隐含的this本类对象的参数
不能重载的运算符:.* (点星) 、::(域访问)、 sizeof 、 ?:、.
赋值运算符重载:
也是默认成员函数之一
void operator= (const classname x)//其中一个参数为this
{
....
}
(流插入运算符的优先级很高)
内置类型的赋值运算符,是从右到左,有返回值,返回值为左操作数
赋值表达式的返回值不能是const,也不能是指针(下面有解释)
上述的赋值运算符重载还有一个问题:
那就是不支持连续赋值
例如有三个类对象:n1、n2、n3
n1 = n2 =n3
试想,这个连续赋值表达式有问题吗?
如果是内置类型就不会有问题
但是,现在他们是自定义类型
注意,赋值表达式是有一个返回值的
这个返回子一般来说默认为左操作数
但是,假如上述写的赋值运算符重载返回值是void
也就是说,没有返回值
那么当n2 = n3执行完之后,就完了
没有返回值了
那么n1怎么办?
所以就会报错
所以需要完善一下我们的赋值运算符重载
而这里的问题根源是没有返回值
既然没有返回值,那我们就给个返回值
返回什么?
返回左操作值
左操作值是什么?
这个赋值重载函数是n2= n3
所以返回n2
也就是*this
但是,还是有问题
什么问题?
这个返回值是一个传值返回
而且返回的是一个自定义类型
返回值本质都是返回一个拷贝
自定义作为返回值,会去调用其对应的拷贝构造
太浪费,也麻烦
所以,更加优化的写法是将返回值设置为引用&
那么,返回值要不要加一个const呢?
不能加
因为对于内置类型的赋值:(a = b )= c;
先把b赋值给a,左边括号内的返回值是左操作数就是a本身,只是被赋值为b了
然后,再将c赋值给a
也就是说,这里的a作为第一个表达式的返回值,是可以修改的
所以,这是C++规定的
所以,最好我们也遵循同样的规则
就是不加const
那么不能返回指针,是为什么呢?很简单,因为指针不能直接进行读写,用引用代替
同时,可以对同一个类对象赋值的时候,加一个特殊处理
例如:a1 = a1;
因为不排除有大可爱会写这样的代码
赋值运算符重载:
所以,赋值运算符重载格式:
1、参数类型const T& 引用传参提高效率
2、返回值类型:T&,返回引用可以提高返回效率,同时可以支持连续赋值
3、检查是否给自己给自己赋值
4、返回*this(即左操作符),也就是和C++一致
同时,运算符重载不可以定义为全局
为什么?
如果定义为全局函数
那么类内部就没有我们定义的赋值重载
那么编译器就会自动生成一个
那么问题就来了:
类内部有一个赋值重载
你全局域也有一个赋值重载
那调用的时候到底听谁呢?
所以,就强制规定,不能定义为全局
因为赋值重载函数是默认的成员函数之一
所以,我们没有显示实现时,编译器就会自动生成一个
默认生成的赋值重载和默认生成的拷贝构造函数一样
对内置类型不调用,直接赋值
但是对于自定义类的赋值,就会调用对应类的赋值重载
总结起来就是:
构造函数和析构函数均对内置类型不处理,对自定义类型调用
拷贝构造和赋值重载对内置类型拷贝不做处理,对自定义类型调用对应的拷贝构造(都是以值得性质,按照字节序进行浅拷贝)
相关知识:
不声明定义分离就是内联
当一个数组被频繁的调用的时候,可以设置为静态,就不必频繁的开辟空间
两个同时存在的变量才叫赋值,否则是拷贝构造
先-后-=
因为减法直接在引用上进行处理,不需要拷贝一份新的
但是-=需要拷贝一份对象进行处理返回
前置++和后置++怎么处理?
强制处理:
void namespace::opraretor++()//前置
void namespace::opraretor++(int)//后置
调试是可以拖的(free不可以)
全局、静态可以使用引用返回,比较方便,可以直接读写
拷贝构造是将一个已经创建的、同类型的作为参数,拷贝到另外一个类对象。是初始化
但是赋值运算重载是对已经存在的两个类对象,将一个类对象赋值给另外一个类对象