派生类如何通过公有成员函数访问基类私有成员变量?
实现方法
C++的访问控制规则明确规定:类的private成员仅允许类自身的成员函数、友元访问,派生类默认没有直接访问权限。你要求不修改基类中a的private修饰符,有两种合规可落地的实现方式:
方案1:给基类补充公有的读写接口(优先使用,符合封装规范)
你现有代码已经实现了读私有成员的getA()方法,只需要在基类A的公有区域补充对应的写方法即可。派生类直接调用这两个公有方法,就能随时读取、修改私有成员a,全程不需要改动a本身的private属性。
#include <iostream> using namespace std; class A { private: int a = 19; public: // 读接口 int getA() { return a; } // 新增写接口,不触碰a的private修饰符 void setA(int val) { a = val; } }; class B : public A { public: void getAatB() { cout << "读取到a的值:" << getA() << endl; } void setAatB(int newVal) { // 调用基类接口修改值 setA(newVal); } }; int main() { B b; b.getAatB(); // 输出初始值19 b.setAatB(100); b.getAatB(); // 输出修改后的值100 return 0; }
这种写法是工业界的标准实践:私有成员的读写逻辑全部收拢在基类内部,后续如果要给a增加校验规则(比如限制取值范围、修改时打日志),只需要调整基类的getA/setA逻辑即可,派生类代码不需要做任何改动。
方案2:将派生类声明为基类的友元类(非必要不使用)
如果你需要在派生类中直接操作a、不想通过接口间接调用,可以在基类中声明派生类B为友元,这样B的所有成员函数就拥有了直接访问A私有成员的权限,同样不需要修改a的private修饰符。
#include <iostream> using namespace std; // 前置声明派生类 class B; class A { // 声明B为友元类 friend class B; private: int a = 19; public: int getA() { return a; } }; class B : public A { public: void getAatB() { // 友元权限下可以直接访问基类私有成员a cout << "读取到a的值:" << a << endl; } void setAatB(int newVal) { // 直接修改a的值 a = newVal; } }; int main() { B b; b.getAatB(); // 输出19 b.setAatB(100); b.getAatB(); // 输出100 return 0; }
这种写法的缺陷很明显:友元关系直接破坏了类的封装性,相当于给派生类开了访问基类内部实现的后门,后续如果基类调整a的类型、存储位置,所有直接访问a的派生类代码都要同步修改,维护成本很高,除非有特殊需求否则不要用。
注意:完全不修改类A的代码就能让派生类访问其私有成员的“奇技淫巧”(比如通过指针偏移、强转绕过访问控制)都属于未定义行为,不同编译器、不同编译优化等级下运行结果可能完全不同,生产环境绝对禁止使用。
内容的提问来源于stack exchange,提问作者user19417626
相关产品推荐
相关产品推荐

