如何让Other::second_function()访问HavePrivateMember的私有成员set_member
问题描述
需要让Other::second_function()能够访问HavePrivateMember类的私有成员函数set_member,原始代码如下:
class HavePrivateMember { private: int _m_member; void set_member(int val) { _m_member = val; } }; class OtherBase { }; class Other : public OtherBase { virtual void first_function(); // 无访问权限 virtual void second_function(); // 需访问HavePrivateMember::set_member };
尝试在Other::second_function()内定义嵌套类PenetratingClass并将其声明为HavePrivateMember的友元,但运行报错:
class HavePrivateMember { friend class PenetratingClass; private: int _m_member; void set_member(int val) { _m_member = val; } }; class Other : public OtherBase { virtual void second_function() { HavePrivateMember has_private_obj; class PenetratingClass { public: void penetrate(HavePrivateMember& has_private_obj) { has_private_obj.set_member(5); } }; PenetratingClass my_penet; my_penet.penetrate(has_private_obj); } };
报错信息:
error: void HavePrivateMember::set_member(int) is private
错误原因
你之前的方案失效是因为函数内部定义的局部类PenetratingClass,和HavePrivateMember里声明友元的PenetratingClass不是同一个类。友元声明里的PenetratingClass是全局命名空间下的类,而你在second_function里定义的是函数作用域内的局部类,两者毫无关系,自然无法获得访问权限。
正确实现方案
方案一:将穿透类放在Other的类作用域下
把PenetratingClass定义在Other类内部(而非函数内),然后在HavePrivateMember里明确声明这个嵌套类为友元:
// 前置声明Other类,因为HavePrivateMember需要引用它的嵌套类 class Other; class HavePrivateMember { // 明确声明Other的嵌套类为友元 friend class Other::PenetratingClass; private: int _m_member; void set_member(int val) { _m_member = val; } }; class OtherBase { }; class Other : public OtherBase { public: // 在Other类作用域下定义穿透类 class PenetratingClass { public: void penetrate(HavePrivateMember& obj) { obj.set_member(5); } }; virtual void first_function(); virtual void second_function() { HavePrivateMember has_private_obj; PenetratingClass my_penet; my_penet.penetrate(has_private_obj); } };
方案二:直接让Other::second_function成为友元
如果不需要额外的穿透类,可以直接把Other的second_function声明为HavePrivateMember的友元,注意前置声明的顺序:
// 前置声明Other类 class Other; class HavePrivateMember { // 直接声明Other的成员函数为友元 friend void Other::second_function(); private: int _m_member; void set_member(int val) { _m_member = val; } }; class OtherBase { }; class Other : public OtherBase { public: virtual void first_function(); virtual void second_function() { HavePrivateMember has_private_obj; has_private_obj.set_member(5); // 直接访问私有成员函数 } };
补充说明
- 方案一的优势是能把访问私有成员的逻辑封装在穿透类中,避免
second_function直接操作私有成员,更符合封装原则。 - 方案二更简洁,适合仅
second_function需要访问私有成员的场景。
内容的提问来源于stack exchange,提问作者bochaltura
相关产品推荐
相关产品推荐

