1.在C++中,我们使用类对数据进行了隐藏和封装,类的数据成员一般都定义为私有成员,成员函数一般都定义为公有的,以此提供类与外界的通讯接口。但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。
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的友元,同样要看类中是否有相应的申明
《windows环境多线程编程原理与应用》中解释:
如果将类的封装比喻成一堵墙的话,那么友元机制就像墙上了开了一个门,那些得
到允许的类或函数允许通过这个门访问一般的类或者函数无法访问的私有属性和方
法。友元机制使类的封装性得到消弱,所以使用时一定要慎重。
3.代码实例
(1)分别定义一个类A和类B ,各有一个私有整数成员变量通过构造函数初始化;类A有一个成员函数Show(B &b)用来打印A和B的私有成员变量,请分别通过友元函数和友元类来实现此功能。使用友元类 和 友元函数实现:
#include <iostream>
using namespace std;
class B;
class A;
void Show( A& , B& );
class B
{
private:
int tt;
friend class A;
friend void Show( A& , B& );
public:
B( int temp = 100):tt ( temp ){}
};
class A
{
private:
int value;
friend void Show( A& , B& );
public:
A(int temp = 200 ):value ( temp ){}
void Show( B &b )
{
cout << value << endl;
cout << b.tt << endl;
}
};
void Show( A& a, B& b )
{
cout << a.value << endl;
cout << b .tt << endl;
}
int main()
{
A a;
B b;
a.Show( b );
Show( a, b );
return 0;
}
-----------------------------------------------------------------------------------------------
#include <iostream>
#include <string>
using namespace std;
//友元类
class cFriend
{
private:
int va;
int vb;
public:
cFriend() { va = 0; vb = 0; }
cFriend(int a,int b) { va = a; vb = b; }
~cFriend() { cout << "执行结束!!!" << endl; }
void set_va(int a) { va = a; }
void set_vb(int b) { vb = b; }
void disp();
friend class cFriends;
};
class cFriends
{
private:
int x;
int y;
public:
cFriends() { x = 0; y = 0; }
cFriends(int a, int b) { x = a; y = b; }
~cFriends() { cout << "友元类调用结束!!!" << endl; }
void disps() { cout << "友元类显示:" << endl; cout << " x = " << x << endl; cout << " y = " << y << endl; }
void dispc(cFriend data);
};
void cFriends::dispc(cFriend data)
{
cout << "友元类访问:" << endl;
cout << " va = " << data.va << endl;
cout << " vb = " << data.vb << endl;
}
void cFriend::disp()
{
cout << "成员函数调用:" << endl;
cout << " va = " << va << endl;
cout << " vb = " << vb << endl;
}
int main()
{
cFriend data1(4, 5);
cFriends data2(5, 6);
data1.disp();
data2.disps();
data2.dispc(data1);
return 0;
}
4.总结
友元类虽然好用,但是破坏了面向对象的封装特性。