c++基础知识杂记(Day5类与友元)

1.运算符重载限制

1.重载后的运算符必须至少有一个是用户定义的类型,这将防止用户为标准类型重载运算符。
2.使用运算符不能违反运算符原来的句法规则。如,不能将求模运算符(%)重载成为一个操作数:
int x;
Time shiva;
% x; //无效的
%shiva;//无效的
同样不能修改运算符的优先级。因此,如果将加号运算符重载成两个类相加,则新的运算符与原来的加号具有相同的优先级。
3.不能创建新的运算符。如,不能定义operator**()函数来表示幂。
4.不能重载以下运算符。
sizeof, . , .* , ::。
5.可重载的运算符:
+-*/%^..等
6.大多数通过成员函数或非成员函数进行重载,但下面的只能通过成员函数进行重载。
=,()//函数调用运算符,[]//下标运算符,->//通过指针访问类成员的运算符。

2友元函数

友元函数是非成员函数,可以访问类的私有成员。

1.为什么需要友元函数?

 重载乘法运算符: 
 class Time 
 { 
 private:
  	int hours;
  	 int minutes;
 public:
  	Time opreator*(double n) const;
  };
  
 Time Time::opreator*(double n) const
  {
    	Time result;
    	 long totalminutes = hours * n * 60 + minutes * n;
    	 result.hours = totalminutes /60;
    	 result.minutes = totalminutes %60; return result;
   }
  //调用: 
  Time adjusted;
  Time weeding(2,30);
 adjusted = weeding* 1.5;
 // A * B 重载乘法运算符与重载加法运算符的区别是它使用了两种不同的类型,一种是Time,一种是double。也就是+和-结合的是两个Time值,而乘法是将double和Time值结合在一起。这限制了该运算符的使用方式。左侧的操作数是调用对象。
 A = B*1.5; 
将被转换成为:
A=B.operator*(1.5);
但是下面的语句应该是怎么样的?	
A= 1.5*B;//cannot correspond to a member function。
解决这个问题还有另一种方式; 
Time operator*(double m, const Time& t);
但是有新问题,非成员函数不能直接访问类的私有数据,至少常规非成员函数不可以访问。友元函数可以访问类的私有成员。 

创建友元函数: 
friend Time operator*(double m, const Time& t);//声明友元函数 
1.虽然operator*()函数是在类中声明的,但它不是成员函数,因此不能使用成员运算符来调用。
2.虽然operator*()函数不是成员函数,但它与成员函数的访问权限相同 //定义友元函数 因为友元函数不是成员函数,所以不需使用Time::,在关键字中也不用使用friend。 
       //调用
       Time opreator*(double n,const Time &t) const  
       {   
       		Time result;
       	         long totalminutes = t.hours * n * 60 + t.minutes * n;
       	         result.hours = totalminutes /60;
       	         result.minutes = totalminutes %60; 
       	         return result; 
       	 }
有了上述定义后,下面的语句:
A  = 1.5 * B;
将转换成为如下语句,从而调用刚才定义的非成员友元函数:
A = operator*(1.5, B);
注意:类的友元函数是非成员函数,其访问权限与成员函数相同。

2.常用的友元:重载<<运算符

可以对<<运算符进行重载,使之能与cout一起来显示对象内容。
假设trip是一个Time对象。为显示Time值。
cout<<trip;
之所以可以这样做,是因为<<是可以被c++重载的。ostream类对该运算符进行了重载,将其转换为一个输出工具。cout是一个ostream对象,能够识别所以c++的基本类型。
1.<<的第一种重载版本
要使Time类知道使用cout,必须使用友元函数。是因为下面语句使用两个对象,其中第一个是ostream类对象(cout);
cout<<trip;
如果使用一个Time成员函数重载<<,Time对象将是第一个操作数,就像使用成员函数重载*运算符那样。这意味着必须这样使用:
trip<<cout;
但是通过友元函数,可以像下面这样重载运算符:
void operator<<(ostream & os, const Time & t)
{
	os<<t.hours<<"hours"<<t.minutes<<"minutes";
}
这样就可以使用下面的语句:
cout<<trip;

注意:友元还是非友元?
新的Time类声明使oper<<()函数成为Time类的一个友元函数。
但该函数不是ostream类的友元(尽管对ostream类并无害处)。
operat<<()函数接受一个ostream参数和一个Time参数,因此表面看起来必须同时是这两个类的友元。
然而,看代码会发现,尽管该函数访问了Time对象各个长城源,但从始至终都将ostream对象作为一个整体使用。
因为operator<<()直接访问Time对象的私有成员,所以它必须是Time类的友元。
但由于它并不直接访问ostream对象的私有成员,所以并不一定必须是ostream类的友元。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值