First, let us examine how the Controlling Access to Class Members is defined:
Member-Access Control
Type of Access | Meaning |
---|---|
private | Class members declared as private can be used only by member functions and friends (classes or functions) of the class. |
protected | Class members declared as protected can be used by member functions and friends (classes or functions) of the class. Additionally, they can be used by classes derived from the class. |
public | Class members declared as public can be used by any function. |
seems,protected is directly related with friend classes or functions.
[摘自wikipedia] A friend function is used in object-oriented programming to allow access to private or protected data in a class from outside the class. Normally a function which is not a member of a class cannot access such information; neither can an external class. Occasionally such access will be advantageous for the programmer; under these circumstances, the function or external class can be declared as a friend of the class using the friend keyword. The function or external class will then have access to all information – public, private, or protected – within the class.
This procedure should be used with caution. If too many functions or external classes are declared as friends of a class with protected or private data, necessary data security may be compromised, as well as the encapsulation of separate classes in object-oriented programming.
example 1: Matrix 可以与Vector相乘,由于Matrix和Vector都会把数据隐藏起来,Multiply这个函数又不能定义为某个类的成员函数,因为定义在任何一个类中都无法访问另外一个类的private数据,这时就可以使用友元来定义。 当然在C#和Java中可以使用接口来实现。
example 2: 使用friend可以实现定制用户的使用习惯,比如Matrix m的转置矩阵可以用m.inv(),但是如果用户想用inv(m)来表示转置矩阵怎么办呢,就可以把inv作为friend函数就可以了。还有一种类似的情况。比如有个类X可以和整数进行四则运算,在X中重载+ - * / 四则运算符,但是这样也只能实现X x; x=x+2;x =x*3;这种类类型在运算符左边的情况,如果你想写成x=2+x;就需要用友元的帮助了。
采用类的机制后实现了数据的隐藏与封装,类的数据成 员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地 访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少 了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。
何时使用友元:
(1) 关注性能;
(2) 支持某种特定的使用习惯;
使用友元类时注意:
(1) 友元关系不能被继承。
(2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
(3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明