友元
前面加friend关键字,可声明为友元
友元函数
类A的友元函数可以访问类A的私有成员
(通常要提前声明其他类便于使用)
友元类
类A的友元类B的所有成员函数都可以访问类A的私有成员
- 友元类之间的关系不能传递,不能继承
运算符重载
作用
扩展运算符的作用范围,让两个对象也能进行运算操作,比如复数求和。
重载
实质上就是函数重载,对不同的对象(实参)可以实现不同的功能
形式上是把含运算符的表达式转换成对运算符函数的调用
形式
返回值类型 operator 运算符(形参表){
...
}
既可以重载为成员函数,也可以重载为普通函数
c=a+b; //等价于c=operator+(a,b);普通函数
a-b; //等价于a.operator(b);成员函数
赋值运算符的重载
赋值运算符‘=’只能重载为成员函数
问题1:
如果有s = s;这样的语句呢?
问题2:
为什么返回值类型要是string &呢?
对运算符进行重载时,应尽可能保留运算符原有的特性(结合律、交换律等)
为了避免指向同一个地址空间,复制构造函数也要自己编写
运算符重载为友元
使用情景
重载为成员函数不能满足要求,重载为普通函数又不能访问私有成员
比如,重载为成员函数时,
c = 5 + c; //等价于5.operator(c),编译出错
解决方法
将其重载为普通函数,这样可以使上述语句不会出错;(原有的成员函数还在)
声明其为友元函数,则可以访问类的私有成员
流插入运算符和流提取运算符的重载
即移位运算符"<<" ">>"的重载
首先,cout实际上是iostream中定义的ostream类的一个对象,移位运算符在其中被重载
对于以下语句,是怎么实现的呢?
cout<<a.name<<b; //相当于cout.operator<<(a.name).operator<<(b)
显然,对于cout<<a.name;和cout<<b;分别实现都是很简单的,只要和之前一样对运算符进行重载即可。
但问题是,怎么让上述语句成立呢?
由前面我们知道,要调用运算符函数,运算符"<<"前面必须是一个对象,在这里则应该是cout对象,即"cout<<a.name"仍然应该返回一个cout对象
所以流插入运算符重载为函数返回值类型必须是ostream &,即返回cout本身
这样就相当于从左到右逐步执行cout语句
自增、自减运算符的重载
为了区分前置、后置表达式,C++规定,前置运算符作为一元运算符重载,后置作为二元运算符(多一个没用的参数)
++i; //相当于operator++(i)
i++; //相当于operator++(i, 0)
由于这两条语句功能不同,所以要返回的值也不同。
-
前者要返回的是修改后的值,所以返回的是对象的引用(修改后)
-
而后者要返回的是修改前的值,所以要在函数中声明一个临时的对象,且最终也要返回一个对象。在此过程中,会调用(复制)构造函数、析构函数,因此开销更大
所以在程序中,应该尽量用++i的形式
程序设计与算法(三)C++面向对象程序设计 https://www.bilibili.com/video/BV1Ns411n7ui?p=11