C++笔记(七)

友元-----(友元函数)

C++控制对类对象私有部分的访问。通常,公有类方法提供唯一的访问途径,但是有时候这种限制太严格,以至于不适合特定的编程问题。在这种情况下,C++提供了另外一种形式的访问限权:友元的种类:

  • 友元函数
  • 友元类
  • 友元成员函数

通过让函数成为类的友元,可以赋予函数与类的成员函数相同的访问权限

1.为何需要友元
看一个例子:

A=B*2.75

其中A,B是同一类型的类。被转换为下面的成员函数调用:

A=B.operator*2.75

但是如果这样的语句该如何操作呢?

A=2.75*B

从概念上看,2.75B与B2.75相同,但第一个表达式不对应于成员函数,因为2.75不是类的对象。记住,左侧的操作数应是调用对象,但是2.75不是对象。因此,编译器不能使用成员函数调用来替换该表达式。

解决方法:
一:告诉每一个人只能按照B*2.75这种格式来编写。
二:非成员函数(大多数运算符都可以通过成员或者非成员函数来重载)。非成员函数不是由对象调用,它使用的所有值(包括对象)都是显式参数。编译器能够将下面的表达式:

A=2.75*B

与下面的非成员函数调用匹配:

A=operator*2.75,B)

该函数原型为:

Myclass operator(double m,const Myclass & t)

对于非成员重载运算符函数来说,运算符表达式左边的操作数对应于运算符的第一个参数,运算符表达式右边的操作数对应于运算符的第二个参数。

使用非成员函数可以按照所需的顺序获得操作数,但引发一个问题:非成员函数不能直接访问类的私有数据,至少常规非成员函数不能访问。

但是有一类特殊的非成员函数可以访问类的私有成员,它们就是友元函数

2.创建友元

创建友元函数的第一步就是将其原型放在类声明中,并在原型声明前加上关键字friend:

friend A operator*double m,const A &t)

该原型意味着下面两点:

  • 虽然operator * ()函数在类中声明的,但它不是成员函数,因此不能使用成员运算符来调用
  • 虽然operator *()函数不是成员函数,但它与成员函数的访问权限一致

第二步就是编写函数定义。因为它不是成员函数,所以不要使用A::限定符。另外,不要在定义中使用关键字friend 。定义应该如下:

A operator*double m,const A &t)
{
	t.私有数据
	return xx;
}

3.常用的友元
一个很有用的类特征是,可以对<<运算符进行重载,使之能与cout一起来显示对象的内容。

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

2.<<的第二种重载版本
前面介绍的实现有一个问题。像下面这样的语句可以正常工作:

cout<<trip;

但这种实现不允许像通常那样重新定义的<<运算符与cout一起使用:

cout<<"trip time"<<trip<<"tuesday \n"<<endl;  错的

理解out操作:
看下面语句:

int x=5;
int y=8;
cout<<x<<y;

C++从左到右读取输出语句:

(cout<<x) <<y;

正如iostream中定义的那样,<<运算符要求左边是一个ostream对象。显然,因为cout是ostream对象,所以表达式cout<<x满足这种要求。然而,因为表达式cont<<x位于<<y的左侧,所以输出语句也要求该表达式是一个ostream类型的对象。因此,ostream类将operator<<()函数实现为返回一个指向ostream对象的引用。具体地说,它返回一个指向调用对象(这里是cout)的引用,表达式(cout<<x)本身就是ostream对象cout,从而可以位于<<运算符的左侧。

修改operator<<()函数,让它返回ostream对象的引用:

ostream & operator <<(ostream &os ,const Time &t)
{
	os<<t.hours<<"hours,"<<t.minutes<<"minutes";
	return os;
}

下面的语句:

cout<<trip;

将被转换为下面的调用:

operator<<(cout,trip)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值