代码改变世界

详解C++ friend关键字

2016-03-09 18:51  想打架的蜜蜂  阅读(2513)  评论(0编辑  收藏  举报

详解C++ friend关键字

http://blog.csdn.net/lwbeyond/article/details/7591415

概述:

1. 为什么要使用友元?

通常对于普通函数来说,要访问类的保护成员是不可能的,如果想这么做那么必须把类的成员都生命成为 public( 共用的) ,然而这做带来的问题遍是任何外部函数都可以毫无约束的访问它操作它;另一种方法是利用 C++ 的 friend 修饰符,可以让一些你设定的函数能够对这些私有或保护数据进行操作。

2. 使用友元有哪些缺点?

使用友元的同时也破坏了类的封装特性,这即是友元最大的缺点。当对外声明为友元后,你的所有细节全部都暴露给了对方。

就好像你告诉你朋友你很有钱这个密秘,进而又把你有多少钱,多少古董,多少家产,多少小妾等等所有的家底全给他说了。 

3. 友元怎样理解?

定一个友元函数,或是友元类,就是告诉对方:我的所有元素对你是开放的。这种 friend 是建立在灰常灰常灰常信任对方的基础上的。

一. 普通函数做为类的一个友元函数

在类里声明一个普通函数,在前面加上 friend 修饰,那么这个函数就成了该类的友元。

这时这个普通函数可以访问该类的一切成员。 

代码如下:

[cpp] view plain copy
 
  1. #include <iostream >      
  2. using  namespace  std;    
  3.   
  4. class  MyClass  
  5. {  
  6. public :      
  7.     MyClass(string name)      
  8.     {      
  9.         m_name = name;  
  10.     }  
  11.   
  12.     //声明一个友元函数  
  13.     friend  void  Display(MyClass &mycalss);  
  14.   
  15. Protected:  
  16.     string  m_name;  
  17. };  
  18.   
  19. //定义这个友元函数  
  20. //写成 void MyClass::Display(MyClass &mycalss)    
  21. void  Display(MyClass &mycalss)  
  22. {    
  23.     cout << "Access Protected data : "<< mycalss.m_name << endl;    
  24. }    
  25.   
  26. //测试  
  27. int main(int argc,char* argv[])  
  28. {  
  29.     MyClass test("Class A");    
  30.       
  31.     Display(test);  
  32.   
  33.     return 0;  
  34. }  

说明:

1. 声明这个友元函数可以在任何地方,可以在 public、protected 当然也可以在 privated 里。

2. 在这个友元函数里,你可以访问这个类里的所有的成员,所有的成员函数,而不管它是不是 public、protected 或 privated 的。

3. 定义友元函数时,不能写成 void MyClass::Display(MyClass &mycalss) 这点要注意。

二. 一个普通函数可以是多个类的友元函数

在每个类里面都有一个友元函数的声明,声明可以有多个,但定义只能有一个。
代码如下:

[cpp] view plain copy
 
  1. #include <iostream >      
  2. using  namespace  std;  
  3.   
  4. class MyClass_B;  
  5.   
  6. class MyClass_A  
  7. {  
  8. public:      
  9.     MyClass_A(string name)      
  10.     {      
  11.         m_name = name;  
  12.     }  
  13.   
  14.     //声明一个友元函数  
  15.     friend void Display(MyClass_A &myA, MyClass_B &myB);  
  16.   
  17. private:  
  18.     string m_name;  
  19. };  
  20.   
  21.   
  22. class MyClass_B  
  23. {  
  24. public:      
  25.     MyClass_B(string name)      
  26.     {      
  27.         m_name = name;  
  28.     }  
  29.       
  30.     //注意,又声明一个友元函数  
  31.     friend void Display(MyClass_A &myA, MyClass_B &myB);  
  32.       
  33. private:  
  34.     string m_name;  
  35. };  
  36.   
  37. //定义这个友元函数  
  38. void  Display(MyClass_A &myA, MyClass_B &myB)  
  39. {  
  40.     cout << "MyClass A : "<< myA.m_name << endl;  
  41.     cout << "MyClass B : "<< myB.m_name << endl;  
  42. }  
  43.   
  44. //测试代码  
  45. int main(int argc,char* argv[])  
  46. {  
  47.     MyClass_A testA("Class A");    
  48.     MyClass_B testB("Class A");    
  49.       
  50.     Display(testA, testB);  
  51.   
  52.     return 0;  
  53. }  

同样的,这个友元函数,可以访问这两个类的所有元素。

三. 一个类的成员函数也可以是另一个类的友元

从而可以使得一个类的成员函数可以操作另一个类的数据成员

[cpp] view plain copy
 
  1. #include <iostream >      
  2. using  namespace  std;    
  3.   
  4. class MyClass_B;  
  5.   
  6. //A 类  
  7. class MyClass_A  
  8. {  
  9. public:      
  10.     MyClass_A(string name)      
  11.     {      
  12.         m_name = name;  
  13.     }  
  14.   
  15.     void Function(MyClass_B &myB);  
  16.   
  17. private:  
  18.     string m_name;  
  19. };  
  20.   
  21. //B 类  
  22. class MyClass_B  
  23. {  
  24. public:      
  25.     MyClass_B(string name)  
  26.     {  
  27.         m_name = name;  
  28.     }  
  29.       
  30.     //友元函数声明,注意和普通函数的区别  
  31.     friend void MyClass_A::Function(MyClass_B &myB);  
  32.       
  33. private:  
  34.     string m_name;  
  35. };  
  36.   
  37. //函数定义  
  38. void MyClass_A::Function(MyClass_B &myB)  
  39. {  
  40.     cout<<myB.m_name<<endl;  
  41. }  
  42.   
  43. //测试代码  
  44. int main(int argc,char* argv[])  
  45. {  
  46.     MyClass_A testA("Class A");    
  47.     MyClass_B testB("Class B");    
  48.       
  49.     testA.Function(testB);  
  50.   
  51.     return 0;  
  52. }  

我们可以看到,B 类,对 A 类其中的一个函数开放,其结果是这个函数可以访问 B 类的所有元素。

四. 整个类也可以是另一个类的友元 

友类的每个成员函数都可以访问另一个类的所有成员。 

示例代码如下:

[cpp] view plain copy
 
  1. #include <iostream >      
  2. using  namespace  std;    
  3.   
  4. //类 A  
  5. class MyClass_B;  
  6.   
  7. class MyClass_A  
  8. {  
  9. public:      
  10.     MyClass_A(string name)      
  11.     {      
  12.         m_name = name;  
  13.     }  
  14.   
  15.     //友元类声明  
  16.     friend class MyClass_B;  
  17.   
  18. private:  
  19.     string m_name;  
  20. };  
  21.   
  22. //类 B  
  23. class MyClass_B  
  24. {  
  25. public:      
  26.     MyClass_B(string name)  
  27.     {  
  28.         m_name = name;  
  29.     }  
  30.       
  31.     void Display(MyClass_A &myA);  
  32.       
  33. private:  
  34.     string m_name;  
  35. };  
  36.   
  37. //成员函数  
  38. void MyClass_B::Display(MyClass_A &myA)  
  39. {    
  40.     cout<<myA.m_name<<endl; //访问A的私有成员  
  41.   
  42.     MyClass_A test("test");  
  43.   
  44.     cout<<test.m_name<<endl; //好像A的所有元素在B里都存在一样  
  45. }  
  46.   
  47. //测试代码  
  48. int main(int argc,char* argv[])  
  49. {  
  50.     MyClass_A testA("Class A");    
  51.     MyClass_B testB("Class B");    
  52.       
  53.     testB.Display(testA);  
  54.   
  55.     return 0;  
  56. }  

此时B可以访问A的所有元素,就好像A在B里面一样。

五. 总结

简单的说就是:声明一个友元函数或者是友元类,就是要把自己完全暴露给对方