标准C++语言-操作符函数重载

一、操作符函数重载

  • 操作符函数(运算符函数)
    • 在C++中针对类类型对象的运算符
    • 符号本身不支持真正的运算操作
    • 编译器把运算翻译成运算符函数
    • 可以针对自定义的类类型设计它独有的运算功能。
  • 操作符函数重载(运算符函数重载)
    • 各种运算已经具备一些功能,再次实现它的就叫作运算符函数重载。
  • 双目运算符
    • a+b
      • 成员函数: a.operator+(b);
      • 全局函数: operator+(a,b);
  • 单目运算符
    • !a
      • 成员函数: a.operator!(void);
      • 全局函数: operator!(a);

二、双目操作符函数重载

  • 成员函数
const 类 operator#(const 类& that) const
{
	return 类(参数#参数);
}
  • 注意:双目运算符的运算结果是个右值,返回值应该加const,然后为了const对象能够调用参数应写const,函数也应该具备const属性。

  • 全局函数
const 类 operator#(const 类& a,const 类& b)
{

}
  • 注意:全局函数不是函数,可能会访问类的私有成员,解决这种问题可以把函数声明为类的友元函数(友元不是成员)。
  • 友元:在类的外部某个函数中想访问类的私有成员(public/protected/private)时,需要所在的函数声明为友元,但友元只是朋友,因此它只有访问权,没有实际的拥有权(其根本原因是它没 this 指针)。
  • 友元声明:把函数的声明写一份到类中,然后在声明前加上friend关键字,使用友元既可把操作符函数定义为全局的,也可以确保类的封装性。
  • 注意:友元函数与成员函数不会构成重载关系,因为它们不在同一个作用域内。

三、赋值类型的双目操作符

  • 成员函数
类& operator#(const 类& that)
{

}
  • 全局函数
类& operator#(cosnt 类& a,const 类& b) 
{

}
  • 获取单参构造赋值运算的调用方式
    • String str = "sunll"; // 会调用单参构造,而不调用赋值运算符
    • str = "hehe";
  • 左操作数据不能具有const属性
    • 成员函数不能是常函数
    • 全局函数第一个参数不能有const属性

四、单目操作符函数重载

  • 成员函数
const 类 operator#(void) const
{

}
  • 全局函数
const 类 operator#(const 类& that)
{

}
  • 前++/–
类& operator#(void)
{

}
类& operator#(类& that)
{

}
  • 后++/–(哑元)
const 类& operator#(int)
{

}
const 类& operator#(类& that,int)
{

}

五、输入输出操作符重载

  • contostream 类型的对象
  • cinistream 类型的对象。
  • 如果 <</>> 运算实现为成员函数,那么调用者应该是ostream/istream,而我们无权增加标准库的代码,因此输人/输出运算符只能定义为全局函数。
ostream& operator<<(ostream& os,const 类& p)
{

}
istream& operator>>(istream& is,类& p)
{

}
  • 注意:在输入输出过程中,cin/cout会记录错误标志,因此不能加const属性。

六、特殊操作符

  • 下标操作符 [ ]
    • 常用于在容器类型中以下标方式获取元素
类型& operator[ ](int i)
{

}
  • 函数操作符 ( )
    • 一个类如果重载函数操作符,那么它的对象就可以像函数一样使用,参数的个数和返回值类可以不确定,这是唯一一个可以有缺省参数的操作符
  • 解引用操作符*
    • 如果一个类重载了*,那么它的对象就可以像指针一样使用
  • 成员访问操作符 ->
    • 如果一个类重载了->,那么它的对象可以像指针一样使用
  • 智能指针
    • 所谓的智能指针就是一个类对象,它支持解引用和成员访问操作符(指针都支持*和->运算
    • 智能指针是一个封装了常规指针的类类型对象,当它离开作用域时,它的析构函数就会自动执行,释放常规指针指向的动态内存(以正确方式创建的智能指针,它的析构函数才能正确执行
  • 常规指针的缺点
    • 当一个常规指针离开它的作用域时,只有该指针所占用的空间被释放,而它指向的内存空间不一定会被释放,在一些特殊情况(人为、业务逻辑的特殊要求)下,free或delete没有执行,就会造成内存泄漏
  • 智能指针与常规指针的不同点
    • 任何时候,一个对象只能使用一个智能指针来指向,而常规指针可以指向多次
    • 智能指针的赋值操作需要经过拷贝构造和赋值构造特殊处理(深拷贝
  • 标准库中的智能指针
    • auto_ptr是标准库中封装好的智能指针,实现了常规指针的基本功能
    • 头文件#include < memory >
    • 用法:auto_ptr<指向的类型> 指针变量名(对象的地址)
    • 局限性
      • 不能跨作用域使用,一旦离开作用域指针变量会释放,指向的对象也会释放
      • 不能放入标准容器
      • 不能指向对象数据
  • new / delete / new[] / delete[] 运算符重载特点
    • C++缺省的堆内存管理器速度较慢,重载后,底层调用malloc/free可以提高运行速度
    • new在失败后会产生异常,而每次使用new时为了安全都应该进行异常捕获,而重载new操作符只需要在操作符函数中进行一次错误处理即可
    • 一些占字节数据比较小的类,频繁使用new,可能会产生大量的内存碎片,而重载new操作后,可以适当的扩大每次申请的字节,减少内存碎片产生的几率
    • 可以记录栈内存使用的信息
    • 可以检查到释放内存失败时的信息,检查到内存泄漏

七、重载操作符的限制

  • 不能重载的操作符
    • 预限定符::
    • 直接成员访问操作符.
    • 三目操作符?:
    • 字节长度操作符sizeof
    • 类型信息操作符typeid
  • 限制规则
    • 重载操作符不能修改操作符的优先级
    • 无法重载所有基本类型的操作符运算
    • 不能修改操作的参数个数
    • 不能发明新的操作符

关于操作符重载的建议:

  • 在重载操作符时要根据操作符实际的功能和意义来确定具体参数,返回值,是否具有 const 属性,返回值是否是引用或者是临时对象。
  • 重载操作符要符合情理(要有意义),要以实际用途为前提前。
  • 重载操作符的意义是为了让对象的操作更简单、方便,而不是为了炫技。
  • 重载操作符要与默认的操作符的功能、运算规则一致,不要出反人类的操作
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值