您的位置:首页 > 其它

友元函数

2015-08-29 18:21 260 查看
1 为什么要用友元函数

结合着类的特性和类中一般成员函数,我们可以这样理解:类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。

为了解决上述问题,提出一种使用友元的方案。友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员(包括字段和函数)。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。

友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样。下面举一例子说明友元函数的应用。

class Point
{
public:
Point(double xx, double yy) { x=xx; y=yy; }
void Getxy();
friend double Distance(Point &a, Point &b);
friend ostream& operator <<(ostream& out,Point& p);
friend istream& operator >>(istream& in, Point& p);
private:
double x, y;
};
void Point::Getxy()
{
cout<<x<<" "<<y<<endl;
}
double Distance(Point &a, Point &b)
{
double dx = a.x - b.x;
double dy = a.y - b.y;
a.Getxy();
return sqrt(dx*dx+dy*dy);
}
ostream& operator <<(ostream& out,Point& p){
out<<p.x<<" "<<p.y;
return out;
}
istream& operator >>(istream& in, Point& p){
in>>p.x>>p.y;
return in;


别的类的成员函数作友元,也就是说这2个类相互调用,这样无论谁定义在前在后,编译时都有冲突。要解决这个问题,只要将类的申明、定义、实装分开就可以了。请注意例子中的解说。

#include <iostream>
#include <string>
using namespace std;

class ca;    //事先申明ca类,确保cb类的定义不出错

class cb {    //在ca类之前定义cb类,确保在ca类里申明cb的test()作友元时不出错
public:
void test(ca& a);    //由于ca类事先申明,这儿不出错
};

class ca {
string id;
void setId(string s) {
id = s;
}
protected:
string name;
void setName(string s) {
name = s;
}
public:
void print() {
cout << id << "  " << name << "  " << endl;
}
friend void cb::test(ca& a);    //申明cb类的test()函数作友元,允许它访问私有保护成员
};

void cb::test(ca& a) {  //作友元的成员函数的实装必须在ca类的后面,否则ca类的成员就未定义了。
a.id = "123";        //这是ca类的私有成员
a.setName("abc");    //这是ca类的保护成员
}

int main ( )
{
ca a;
cb b;
b.test(a);
a.print();

return 0;
}


2 友元类
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。
当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:
friend class 类名;
其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。

例如,以下语句说明类B是类A的友元类:
class A
{

public:
friend class B;

};
经过以上说明后,类B的所有成员函数都是类A的友元函数,能存取类A的私有成员和保护成员。

使用友元类时注意:
(1) 友元关系不能被继承。
(2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
(3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明

#include <iostream>

using namespace std;

class CObj
{
public:
CObj() : mX(0), mY(0) {}
friend class CFriend;
private:
void PrintData() const
{
cout << "mX = " << mX << endl
<< "mY = " << mY << endl;
}
int mX;
int mY;
};

class CFriend
{
public:
CFriend(int x, int y)
{
mObj.mX = x;    //直接调用类CObj的私有数据成员
mObj.mY = y;
}
void ShowData() const
{
mObj.PrintData();   //直接调用类CObj的私有成员函数
}
private:
CObj mObj;
};

int main()
{
CFriend one(3, 4);
one.ShowData();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: