【正确答案】
【答案解析】类具有封装、继承、多态、信息隐藏的特性,只有类的成员函数才可以访问类的标记为private的私有成员,非成员函数可以访问类中的公有成员,但是却无法访问私有成员,为了使非成员函数可以访问类的成员,唯一的做法就是将成员都定义为public,但如果将数据成员都定义为公有的,这又破坏了信息隐藏的特性。而且,对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,从而影响程序的运行效率。
友元正好解决了这一棘手的问题。在使用友元函数时,一般需要注意以下几个方面的问题:
1)必须在类的说明中说明友元函数,说明时以关键字friend开头,后跟友元函数的函数原型,友元函数的说明可以出现在类的任何地方,包括private和public部分。
2)友元函数不是类的成员函数,所以友元函数的实现与普通函数一样,在实现时不用“::”指示属于哪个类,只有成员函数才使用“::”作用域符号。
3)友元函数不能直接访问类的成员,只能访问对象成员。
4)友元函数可以访问对象的私有成员,但普通函数不行。
5)调用友元函数时,在实际参数中需要指出要访问的对象。
6)类与类之间的友元关系不能继承。
友元一般定义在类的外部,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。需要注意的是,友元函数不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。友元函数是指某些虽然不是类成员却能够访问类的所有成员的函数。友元函数的特点是能够访问类中的私有成员的非成员函数。从语法上看,友元函数与普通函数一样,即在定义上和调用上与普通函数一样。成员函数和非成员函数最大的区别在于成员函数可以是虚的,而非成员函数不行。所以,如果有一个函数必须进行动态绑定,就要采用虚函数,而虚函数必定是某个类的成员函数。
友元函数示例如下:
#include<iostream>
#include<string>
using namespace std;
class Fruit
{
public:
Fruit(const string &nst="apple",const string &cst="green"):name(nst),colour(cst)
{
}
~Fruit()
{
friend istream& operator>>(istream&,Fruit&);
friend ostream& operator<<(ostream&,const Fruit&);
void print()
{
cout<<colour<<" "<<name<<endl;
string name;
string colour;
ostream& operator<<(ostream &out,const Fruit &s)//重载输出操作符
{
out<<s.colour<<" "<<s.name;
return out;
}
istream& operator>>(istream& in,Fruit &s)//重载输入操作符
{
in>>s.colour>>s.name;
if(!in)
cerr<<"Wrong input!"<<endl;
return in;
}
int main()
{
Fruit apple;
cin>>apple;
cout<<apple;
return 0;
}
注意:由于VC++6.0自身的Bug,以上程序在VC++6.0编译无法通过,需要在VisualStudio 2005及以上版本下编译才能通过。