前言

简单记录一下C++中的友元,记录于此主要是方便自己查阅和回顾。

正文

定义

友元(使用关键字Friend修饰) 是一个非常强大的特性,它让类的成员函数或全局函数能够访问其他类的私有成员(private)和保护成员(protected)。

优缺点

  1. 优点:某些情况下,能够让代码更加灵活和高效。

  2. 缺点:破坏了封装。

友元函数

友元函数是在类内部声明(用friend关键字修饰)的外部函数,它可以访问该类的私有和保护成员。

友元普通函数

普通函数,然后在类中使用friend修饰和声明,这样此普通函数可以访问此类中的所有成员。

下面是计算面积的函数computerArea,如果在Rectangle类中进行使用friend修饰和声明,那么函数computerArea就可以直接访Rectangle类中的所有成员。

  1. #include <iostream>
  2. #include <cmath>
  3. class Rectangle {
  4. //一个定义为private,一个定义为protected
  5. private:
  6. int height;
  7. protected:
  8. int width;
  9. public:
  10. Rectangle() {
  11. height = 0;
  12. width = 0;
  13. }
  14. Rectangle(int left, int top, int right, int bottom) {
  15. height = abs(bottom - top);
  16. width = abs(right - left);
  17. }
  18. int getHeight() {
  19. return height;
  20. }
  21. int getWidth() {
  22. return width;
  23. }
  24. //使用friend关键字声明为友元
  25. friend int computerArea(Rectangle& rectangle);
  26. };
  27. int computerArea(Rectangle& rectangle) {
  28. //普通函数只能通过public的方法获取
  29. //return rectangle.getHeight() * rectangle.getWidth();
  30. //除了方法,友元函数可以直接访问私有成员
  31. return rectangle.height * rectangle.width;
  32. }
  33. int main()
  34. {
  35. Rectangle rectangle(0, 0, 100, 200);
  36. int area = computerArea(rectangle);
  37. std::cout << rectangle.getWidth() << " * " << rectangle.getHeight() << " = " << area << std::endl;
  38. }
复制

在类内部使用friend声明后,computerArea()可以方法类中所有的成员变量和成员函数。

友元普通函数可以看做类的一个[成员函数],但并非真正类的成员函数,但权限是一样的。

友元类函数

一个类A中使用friend修饰另外一个类B的成员函数C,那么类B的函数C可以访问类A中的所有成员。

下面例子:父亲想获取儿子的零花钱,一般情况,只能通过儿子去存钱罐中拿钱,但是如果声明未友元,父亲可以直接访问儿子的存钱罐。

  1. #include <iostream>
  2. class Son;//提前声明
  3. class Father {
  4. public:
  5. float getPocketMoneyFriend(Son& son);
  6. float getPocketMoney(Son& son);
  7. };
  8. class Son {
  9. private:
  10. float pocketMoney; //零花钱
  11. public:
  12. Son() {
  13. pocketMoney = 1100;
  14. }
  15. //如果通过儿子,只能使用这个函数
  16. float getSonPocketMoney() {
  17. //超过1000时分享零花钱
  18. if (pocketMoney > 1000) {
  19. return pocketMoney - 1000;
  20. }
  21. return 0;
  22. }
  23. //但是申请友元,直接访问儿子存钱罐
  24. friend float Father::getPocketMoneyFriend(Son& son);
  25. };
  26. //友元类
  27. float Father::getPocketMoneyFriend(Son& son) {
  28. //找儿子要钱
  29. //return son.getSonPocketMoney();
  30. //直接访问存钱罐
  31. return son.pocketMoney;
  32. }
  33. //非友元类
  34. float Father::getPocketMoney(Son& son) {
  35. //找儿子要钱
  36. return son.getSonPocketMoney();
  37. }
  38. int main()
  39. {
  40. Father father;
  41. Son son;
  42. float result = father.getPocketMoneyFriend(son);
  43. std::cout << result << std::endl;
  44. result = father.getPocketMoney(son);
  45. std::cout << result << std::endl;
  46. }
复制

从上面可以知道:

  1. 友元类函数(getPocketMoneyFriend)可以访问Son的所有成员

  2. 普通类函数(getPocketMoney)只能通过Son的public方法访问

友元类

除了友元函数,C++ 还允许整个类作为友元类。友元类可以访问另一个类的私有和保护成员。

跟友元类函数的例子差不多,还是父类找儿子要钱,这次把父亲声明未友元类。

  1. #include <iostream>
  2. class Son;
  3. class Father {
  4. public:
  5. float getPocketMoney1(Son& son);
  6. float getPocketMoney2(Son& son);
  7. };
  8. class Son {
  9. private:
  10. float pocketMoney; //零花钱
  11. public:
  12. Son() {
  13. pocketMoney = 1100;
  14. }
  15. float getSonPocketMoney() {
  16. //超过1000时分享零花钱
  17. if (pocketMoney > 1000) {
  18. return pocketMoney - 1000;
  19. }
  20. return 0;
  21. }
  22. friend class Father;
  23. };
  24. float Father::getPocketMoney1(Son& son) {
  25. //找儿子要钱
  26. //return son.getSonPocketMoney();
  27. //直接访问存钱罐
  28. return son.pocketMoney;
  29. }
  30. float Father::getPocketMoney2(Son& son) {
  31. //找儿子要钱
  32. //return son.getSonPocketMoney();
  33. //直接访问存钱罐
  34. return son.pocketMoney;
  35. }
  36. int main()
  37. {
  38. Father father;
  39. Son son;
  40. float result = father.getPocketMoney1(son);
  41. std::cout << result << std::endl;
  42. result = father.getPocketMoney2(son);
  43. std::cout << result << std::endl;
  44. }
复制

从上面可以知道:

  1. 声明友元类后,Father的所有函数都成为友元函数了,都可以访问Son的所有成员

注意

  1. 友元关系是不能传递的,如A是B的友元,B是C的友元,但A不是C的友元

  2. 友元关系是单向的,A是B的友元,A可以访问B的私有属性,反之不成立

  3. 友元关系是不被继承的,A是B的友元,但A的派生类不是B的友元

参考文章

  1. 《C++从入门到精通(第6版)》

  2. C++友元

  3. C++ 友元(Friend)详解

相关文章

暂无评论

none
暂无评论...