本文,暂且记录C++ friend,以后考虑是否需要将public和protected
友元:能够直接访问私有、公有、保护的成员变量
友元的3种
- 友元函数
- 友元类
- 友元成员函数
在为类重载二元操作符(带两个参数的操作符)常需要友元函数,比方说重载*运算符,
a = b * 2.75;
转换为
a = b.operator*(2.75);
但,a = 2.75 * b;
按照操作符的左侧的操作数是调用对象,右侧是被传递对象,将无法解析。
这需要另一个种解决办法,就是:非成员函数(大多数操作符都可以通过成员或非成员函数来重载)。
非成员函数不是由对象调用的,它使用的所有值(包括对象)都是显式参数,这样编译器就能够表达
a = 2.75 * b;
从而,转换为
a = operator*(2.75, b);
<<重载就稍微复杂一点
<<实际上为C/C++的位操作符,将值中的位左移。
但ostream类已经将它多次重载,转换为输出工具。
cout是ostream类的对象,智能识别所有基本类型,我们需要将自己的class让ostream也能识别
并最终完成调用
cout << mycalss;
如果,按照成员函数重载方式实现<<重载,将有
myclass << cout;
这种调用方式,显然看起来并不自然。
成员函数的解析方式已经说了:操作符的左侧的操作数是调用对象,右侧是被传递对象。
下面,就是实现<<重载的两个版本,一般是仅使用第二种,但为了推理,将第一种也推出。
<<的第一种重载版本
声明
void operator<< (ostream &os, const Time &t);
实现
void
//Time:://friend function(non-member function) not to add the class scope
operator* (ostream &os, const Time &t)
{
os << t.hours << " hours, " << t.minutes << " minutes";
}
第一版本,基本满足了上述的要求,就是cout << myclass;
的调用方式,但还不够。
<<的第二种重载版本
声明
friend ostream & operator<< (ostream &os, const Time &t);
实现
ostream &
operator* (ostream &os, const Time &t)
{
os << t.hours << " hours, " << t.minutes << " minutes";
return os;
}
第二版本,能够实现“拼接”的使用方法。
也就是:
cout << "myclass operator<< " << myclass.object << 502 << endl;
这种“拼接“需要返回当前os,为下一个对象输出做铺垫(也就缓冲前一个对象的输出数据而已)