标准C++ -- day05
一、 特殊的运算符重载函数
* -> () [] new delete
-
[ ] 下标运算符
-
想让一个类对象当成数组1一样使用,可以考虑重载下标运算符,例如:vector 等
-
class Array { int* ptr;// 首地址 int cal; // 容量 public: Array(int cal):cal(cal) { ptr = new int[cal]; } int& operator[](int i) { if(0 > i||i >= cal) throw("Array Over Cal"); // 抛异常 return ptr[i]; } }; int main() { Array arr(10); for(int i = 0;i < 10;i++) { try{ arr[i] = i; }catch(const char* msg){ cout << msg << endl; } cout << arr[i] << endl; } }
-
可以考虑在下标重载函数中做非法下标的判断,让下标的使用更安全
-
()函数运算符
-
重载此运算符可以让一个类对象当做函数一样使用
-
注意:( ) \ [ ] 均不能实现为全局运算符函数,只能实现成员函数(C++全局中已经有类似的函数实现,所以不能实现)
-
= 赋值运算符也不能实现为全局函数,因为类内本身一定有一个=赋值运算符成员函数
-
class Func { public: Func(int num=0){} int operator()(int num)const { cout << "()" << endl; } }; Func func(10); // 调用构造函数 func(100); // 输出 ()
-
-
解引用* 和访问成员的运算符 ->
- 重载这两个运算符可以让类对象像指针一样使用,智能指针就是通过重载这两个运算符从而像使用指针一样的类
-
new 、delete 运算符的重载
-
void* operator new(size_t size)
-
C++语法要求重载new运算符的参数必须为size_t,编译器会帮助计算要申请的字节数并传递,返回值必须为void*,编译器会帮助转换成对应的类型指针返回
class Test { int num; public: Test(int num=0):num(num){} void* operator new(size_t size) { return malloc(size); } };
-
-
-
void operator delete(void* ptr)
-
C++语法要求重载delete的参数必须为void,编译器帮助转换成void传递
-
注意:new和delete的成员函数和全局函数的格式一样
-
如果只是针对某个类想要重载它的new、delete时,则写为成员函数
-
如果想要所以类型都执行重载版本,实现为全局函数
-
为什么要重载new\delete?
-
- 可以在重载函数中记录每次分配、释放内存的地址、代码情况、次数情况等到日志中,从而方便检查是否出现内存泄漏,以及泄露位置
- 对于字节少、且频繁申请、释放的对象,可以在重载函数中给它多分配点内存从而减少产生碎片的可能
-
-
如果显式地实现析构函数,则会多申请4字节存储要析构的次数
-
如果不显式实现析构,则不会多申请
二、 重载运算符的限制
- 不能重载的运算符
:: // 域限定符
. // 直接访问成员的运算符
?: // 三目运算符
sizeof // 计算字节数
typeid // 获取类型信息的运算符
- 只能重载为全局函数的运算符
<< // 输出运算符
>> // 输入运算符
- 只能重载为成员函数的运算符
[]
()
=
->
-
运算符重载可以自定义运算符执行过程,但是无法改名运算符的优先级
-
运算符的操作数量也不能改变
-
不能发明新的运算符
建议:
-
重载运算符要遵循一致性原则,不要随意改变运算符本身的含义
-
不要忘记实现运算符重载函数的初衷,为了提高可读性,不要随意炫技