前言
简单记录一下C++中的友元,记录于此主要是方便自己查阅和回顾。
正文
定义
友元(使用关键字Friend修饰) 是一个非常强大的特性,它让类的成员函数或全局函数能够访问其他类的私有成员(private)和保护成员(protected)。
优缺点
优点:某些情况下,能够让代码更加灵活和高效。
缺点:破坏了封装。
友元函数
友元函数是在类内部声明(用friend
关键字修饰)的外部函数,它可以访问该类的私有和保护成员。
友元普通函数
普通函数,然后在类中使用friend修饰和声明,这样此普通函数可以访问此类中的所有成员。
下面是计算面积的函数computerArea,如果在Rectangle类中进行使用friend修饰和声明,那么函数computerArea就可以直接访Rectangle类中的所有成员。
#include <iostream> #include <cmath> class Rectangle { //一个定义为private,一个定义为protected private: int height; protected: int width; public: Rectangle() { height = 0; width = 0; } Rectangle(int left, int top, int right, int bottom) { height = abs(bottom - top); width = abs(right - left); } int getHeight() { return height; } int getWidth() { return width; } //使用friend关键字声明为友元 friend int computerArea(Rectangle& rectangle); }; int computerArea(Rectangle& rectangle) { //普通函数只能通过public的方法获取 //return rectangle.getHeight() * rectangle.getWidth(); //除了方法,友元函数可以直接访问私有成员 return rectangle.height * rectangle.width; } int main() { Rectangle rectangle(0, 0, 100, 200); int area = computerArea(rectangle); std::cout << rectangle.getWidth() << " * " << rectangle.getHeight() << " = " << area << std::endl; }
在类内部使用friend声明后,computerArea()可以方法类中所有的成员变量和成员函数。
友元普通函数可以看做类的一个[成员函数],但并非真正类的成员函数,但权限是一样的。
友元类函数
一个类A中使用friend修饰另外一个类B的成员函数C,那么类B的函数C可以访问类A中的所有成员。
下面例子:父亲想获取儿子的零花钱,一般情况,只能通过儿子去存钱罐中拿钱,但是如果声明未友元,父亲可以直接访问儿子的存钱罐。
#include <iostream> class Son;//提前声明 class Father { public: float getPocketMoneyFriend(Son& son); float getPocketMoney(Son& son); }; class Son { private: float pocketMoney; //零花钱 public: Son() { pocketMoney = 1100; } //如果通过儿子,只能使用这个函数 float getSonPocketMoney() { //超过1000时分享零花钱 if (pocketMoney > 1000) { return pocketMoney - 1000; } return 0; } //但是申请友元,直接访问儿子存钱罐 friend float Father::getPocketMoneyFriend(Son& son); }; //友元类 float Father::getPocketMoneyFriend(Son& son) { //找儿子要钱 //return son.getSonPocketMoney(); //直接访问存钱罐 return son.pocketMoney; } //非友元类 float Father::getPocketMoney(Son& son) { //找儿子要钱 return son.getSonPocketMoney(); } int main() { Father father; Son son; float result = father.getPocketMoneyFriend(son); std::cout << result << std::endl; result = father.getPocketMoney(son); std::cout << result << std::endl; }
从上面可以知道:
友元类函数(getPocketMoneyFriend)可以访问Son的所有成员
普通类函数(getPocketMoney)只能通过Son的public方法访问
友元类
除了友元函数,C++ 还允许整个类作为友元类。友元类可以访问另一个类的私有和保护成员。
跟友元类函数的例子差不多,还是父类找儿子要钱,这次把父亲声明未友元类。
#include <iostream> class Son; class Father { public: float getPocketMoney1(Son& son); float getPocketMoney2(Son& son); }; class Son { private: float pocketMoney; //零花钱 public: Son() { pocketMoney = 1100; } float getSonPocketMoney() { //超过1000时分享零花钱 if (pocketMoney > 1000) { return pocketMoney - 1000; } return 0; } friend class Father; }; float Father::getPocketMoney1(Son& son) { //找儿子要钱 //return son.getSonPocketMoney(); //直接访问存钱罐 return son.pocketMoney; } float Father::getPocketMoney2(Son& son) { //找儿子要钱 //return son.getSonPocketMoney(); //直接访问存钱罐 return son.pocketMoney; } int main() { Father father; Son son; float result = father.getPocketMoney1(son); std::cout << result << std::endl; result = father.getPocketMoney2(son); std::cout << result << std::endl; }
从上面可以知道:
声明友元类后,Father的所有函数都成为友元函数了,都可以访问Son的所有成员
注意
友元关系是不能传递的,如A是B的友元,B是C的友元,但A不是C的友元
友元关系是单向的,A是B的友元,A可以访问B的私有属性,反之不成立
友元关系是不被继承的,A是B的友元,但A的派生类不是B的友元
参考文章
《C++从入门到精通(第6版)》
《》
《