C++子类调用父类protected成员报错:原因与解决方法
子类通过父类指针调用protected成员函数报错的原因与解决方法
先看你给出的代码:
struct A{ protected: virtual void IAmProtected() = 0; }; struct B: public A{ private: A * a; protected: void IAmProtected() override; public: void doSomething(){ a->IAmProtected(); // ERROR: 'IAmProtected' is a protected member of 'A' } };
1. 报错的原因
C++里的protected成员访问规则不是“子类能随便访问父类的protected成员”,而是子类只能访问自身对象继承来的protected成员,不能通过父类类型的指针/引用去访问其他对象(哪怕这个对象实际是子类实例)的protected成员。
你代码里的a是A类型指针,编译器处理a->IAmProtected()时,只会把它当成一个普通的A类对象,此时B作为子类没有权限直接操作这个A类对象的protected成员——protected权限只开放给子类操作自己继承的那部分,不是让子类去操控任意父类对象的protected成员。
2. 解决方法
这里有几种实用的解决思路:
- 修改指针类型为子类类型
如果a实际指向的是B类对象,直接把指针改成B*就行。此时编译器会识别这是B类对象的成员,B作为子类有权访问自身的protected成员:
struct B: public A{ private: B * a; // 改为B类型指针 protected: void IAmProtected() override; public: void doSomething(){ a->IAmProtected(); // 编译正常 } };
- 在父类中增加public接口间接调用
如果a必须是A*,可以在A类里加一个public成员函数,用来封装对IAmProtected()的调用:
struct A{ protected: virtual void IAmProtected() = 0; public: void triggerProtectedFunc(){ IAmProtected(); } }; struct B: public A{ private: A * a; protected: void IAmProtected() override; public: void doSomething(){ a->triggerProtectedFunc(); // 通过public接口调用 } };
- 将子类声明为父类的友元
如果不想改指针类型或加public接口,可以在A类里把B声明为友元,让B有权访问任意A类对象的protected成员:
struct B; // 前置声明 struct A{ protected: virtual void IAmProtected() = 0; friend struct B; // 声明B为友元 }; struct B: public A{ private: A * a; protected: void IAmProtected() override; public: void doSomething(){ a->IAmProtected(); // 编译正常 } };
内容的提问来源于stack exchange,提问作者Mr. Developerdude
相关产品推荐
相关产品推荐

