1. final关键字
final关键字在继承中产生作用,父类虚函数使用了final后,子类无法重写该虚函数
2. 运算符重载
作用: 提高代码可读性,提高类的易用性
使用重载的两种方法:
运算符重载的原则:
- 1. 运算符重载不能改变运算符原有使用方式
- 2. 运算符重载不能改变原有运算符意义
关于赋值运算符
如果自己没有实现,则编译器会提供一个默认的赋值运算符重载,其直接进行浅拷贝操作
经验建议: 一个类要至少实现如下三个, 目的是为了消除编译器实现默认类函数的机会
- 实现默认构造
- 实现拷贝构造
- 重载赋值运算符
来看一个例子:
3. 加号运算符
来看如下加法运算符重载的区别
这两者的效果差不多是一样的
首先看下那个,下面那个首先将参数加到自身的成员属性并返回自身的引用。
而上面那个创建了一个局部对象并将所有操作用在这个局部对象上后返回
有一个小小的区别:
如果是下面那种方式,上图红框所示代码也会改变自身的值,其原因在于下面那种方式是对自身对象进行操作,而上面是一个临时对象
如果使用上面的重载,则会是如下结果:
如果是这样呢? 如何让这样的代码也可以运行:
假设是按照如下进行:
实际上编译器执行的是如下代码:
但可惜的是:
cInt1 + 55 // cInt1.operator+(55);
55 + cInt1 // 这就变成了 55.operator+(cInt1);
虽然平常开发过程中很少会遇到,但如何利用运算符重载解决这个问题?
首先导致这种局面的原因是this指针的位置,由于每个成员函数都隐含一个指向自身对象的指针,该指针一般在参数列表的第一个
也就是说:
// 看上去是这样的
CInteger operator+(int n)
{
CInteger cInt(n);
cInt.m_iNum += m_iNum;
return(cInt);
}
// 实际上是这样的
CInteger operator+(CInteger const *pthis, int n)
{
CInteger cInt(n);
cInt.m_iNum += pthis->m_iNum;
return(cInt);
}
这就导致了+运算符的左侧内容的地址会被this指针指向
这种情况可以使用全局运算符重载的方式解决:
使用全局的运算符重载解决这个问题的原因是因为可以改变this指针的位置,这里的this指针就相当于是CInteger &obj了。
来看一下运行的结果:
当然这样做没有什么意义。
4. 自增(自减运算符)
注意:
后置++是不可以连续进行的,比如:
这里进行了3次后置++,理论上来讲数值应该变成24才对,可这里只执行了一次。
原因在于后置++返回的是一个临时对象,也就是说除了第一次后置++,其他2次都是在临时对象上进行操作的。
5. 关系和逻辑运算符
关系运算符:
<<和>>运算符:
注意,>>和<<运算符必须是全局运算符重载,因为第一个参数是std::cout或者std::cin,其不可能变成如下:
// 不可能!
cout.operator<<(obj);
cin.operator>>(obj);
当采用了全局运算符重载后就可以避免这种情况。
new和delete运算符:
注意,new和delete运算符即使被重载也会执行构造和析构函数
转换运算符:
作用是假设没有重载<<运算符的情况下,这是不被允许的:
为了能够让其成立可以定义上面的换行运算符
这种方式其实用的比较少,注意不要写多了,这会造成困惑。
[]运算符:
()运算符:
可以把对象作为函数来调用
(完)