早之前很少用友元类,直到最近跟某个博主写 Asio 网络库,跟着用到友元类,但是今天却遇到一个问题,通过查询得到解决,特记录于此。不过,在此之前,还是把友元类的基础知识做个记录。
基础知识
友元可以是一个函数,该函数被称为友元函数。
类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
1 |
|
友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。
下面声明 Session 类 是 MsgNode 类的友元类,意味着 Session 类可以访问 MsgNode 类 中所有的成员变量和成员函数(public、protected、private)
1 |
|
注意点
友元并不属于这个类本身,无论是友元函数还是友元类。都不能使用类内的this指针,同时也不可以被继承,如同父亲的朋友不一定是儿子的朋友这个道理。
- 友元关系不能被继承
- 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明
- 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明
遇到的问题:不可访问友元类的继承的私有成员
我要先把类的继承关系罗列出来,才能讲这里的问题:
1 |
|
RecvNode 类 基础自 MsgNode 类,即有部分成员变量来源于它。我在 LogicSystem 类中要去访问 RecvNode 类 中的成员函数,就在 RecvNode 类中把 LogicSystem 声明为 友元,成功访问到 msgID_ 成员函数,但是却不能访问 data_ 成员。
截止,我们提出这个问题:子类从父类继承的成员变量,是属于子类呢还是属于父类呢?
因此可以看出,父类中的所有变量都被子类给继承了下来,都属于子类的一部分。虽然父类中 private
访问权限的成员不能被子类访问,但是仍然属于子类的一部分。同理,在子类继承父类时,除了继承父类中所有的成员变量,也同时继承了除了父类构造函数外的所有成员函数,这样便可以有效节省代码量,提高代码复用效率。
哦,我们知道了!!!父类中 private 访问权限下的成员不能被子类访问,哪怕它属于子类的一部分。那么子类 RecvNode 都不能访问到父类 MsgNode,凭什么你 友元类 LogicSystem 就可以呢?显然 LogicSystem 类也不可以访问。
该怎么做 ?让子类 RecvNode 能访问到父类 MsgNode即可,所以修改父类 MsgNode 的 private 下的成员变量为 protected 即可。你当然也可以修改为 public,那我设置友元类干什么?