一、 操作符函数
在C++中会把运算符当函数处理,一个表达式,其实是调用了很多运算符函数完成计算的;这种特性对内建类型没有什么用处,但是对自建内型数据,却可以进行个性化设计,提高代码的可读性和易用性(如 string 类)
string str;
str += "hehe";
str1 == str2;
运算符函数的格式:
单目运算符:#O 或 O# 会被编译器解释为
[] O::operator#(void)
{
}
返回值不确定,唯一的参数是调用者
全局函数:
[] operator(O&)
{
}
运算符成员函数、全局函数,只能实现一个,不能同时实现
双目运算符:a#b
成员函数:
[] operator#(B& b)
{
}
全局函数:
[] operator(A& a,B& b)
{
}
一、运算类的双目运算符
成员函数:a+b
const T operator+(const T& b) const
{
return T(x+b.x);
}
全局函数:a+b
const T operator+(const T& a),const T& b)
{
return T(a.x+b.x);
}
友元:
在实现类的全局运算符函数时,可能会使用到类的私有成员;如果把私有成员改为 public 或实现 get 函数就打破了类的封装性;最好的解决方法就是给运算符全局函数进行独家授权,这种授权我们叫设置友元函数;方法就是在类中进行声明全局函数,且在声明前加上 friend 关键字
二、输入输出运算符
输出运算符:cout << a << endl;
在 C++中 << >> 运算符不光是可以左移右移,它还是cin 和cout 输入、输出运算符
由于<< 运算符的调用者是cout,所以无法实现出成员运算函数
ostream& operator<<(ostream& os,const T a)
{
return os;
}
输入运算符:cin >> a >> b
istream& operator>>(istream& is,T& a)
{
cout << "请输入a的值:";
return is >> a;
}
由于输入、输出函运算符是由cin、cout调用的,我们无法在ostream、istream类中添加代码,因此只能实现全局运算符函数
三、运算类的单目运算符
++/-- ! ~ * sizeof &(取地址) -(负号)
成员函数:- ! ~
const T operator-(void)
{
return T(-a.x);
}
运算对象可以是常量,运算过程中并不会修改自身的值,而是产生一个临时的计算结果,且计算结果不能被赋值
全局函数:
const T operator-(const T& a)
{
return T(-a.x);
}
四、自变运算符
前自变运算符:++i/--i
成员函数:
const T& operator++(void)
{
x++;
return *this;
}
全局函数:
const T& operator++(void)
{
t.x++;
return t;
}
后自变运算符:i++/i--
成员函数:在参数列表中添加哑元,与前自变区分
const T operator++(int)
{
return T(x++);
}
全局函数:
const T operator++(const T& t,int)
{
return T(t.x++);
}
以下运算符
. :: ?: sizeof typeid(类型信息操作符) 不能被重载
五、特殊的运算符函数
1、下标运算符[]
当想让一个类对象当数组使用时,可以冲在下标运算符,如标准模板库中的vector、list
2、函数运算符()
重载此运算符可以让一个类对象当函数使用
3、解引用和简介成员访问运算符* ->
重载此运算符可以让一个类对象像指针一样操作,智能指针就重载此运算符实现的
4、new/delete的重载
为什么重载new/delete?
1、可以运算符函数中记录
六、智能指针
常规指针的缺点:
当一个常规指针离开作用域时,只有该指针本身所占用内存空间(4自己或8字节)会被释放,而它所指向的内存空间不会被释放
当free、delete、delete[]语句无法执行、忘记执行时就形成了内存泄漏
智能指针的优点:
智能指针是一个封装了常规指针的类类型对象,当它离开作用域时,它的析构函数会自动释放常规指针所指向的内存,这样就做到了自动释放
智能指针与常规指针的相同点:
智能指针虽然是类对象但它重载了*、-> 可以像常规则至臻一样正常使用
智能指针的缺点(局限性):
1、不能跨作用域指针
2、不能多个指针指向一个对象,否则就会重载释放导致内存崩溃
3、不能指向对象数组
4、不能放入容器中
C++中智能指针的使用方法:
#include <menory>
auto_ptr<类型> ptr(new 类型);
ptr就可以像普通指针一样使用了