为何派生类无法访问基类protected函数?求非public化解决方案
问题分析与解决方案
报错原因
C++里protected成员的访问规则是:派生类只能访问自身实例继承而来的基类protected成员,不能访问任意独立基类对象的protected成员。
你代码里的b是一个独立的Base对象(哪怕它实际是C类型,编译器也会按Base类型处理),C作为派生类,没有权限直接调用这个外部对象的protected成员call()。
至于你尝试的using Base::call,它只是把基类的call成员引入到C的作用域里,让你可以直接用this->call()或者call()调用当前C对象自己的call,但依然不能用来访问其他Base对象的call。
可行解决方案(无需把call改成public)
方案1:让Base把C声明为友元
在Base类里添加友元声明,这样C就能访问任意Base对象的protected成员:
class Base { friend class C; // 添加友元声明 protected: void call() const {} }; class C : public Base { public: void func(const Base& b) { b.call(); // 现在可以正常调用 } };
方案2:在Base中添加辅助函数,让派生类间接调用
在Base里新增一个protected的辅助函数,用来调用其他Base对象的call,派生类可以通过自身实例调用这个辅助函数:
class Base { protected: void call() const {} // 新增辅助函数 void invoke_call(const Base& b) const { b.call(); } }; class C : public Base { public: void func(const Base& b) { invoke_call(b); // 通过当前对象的辅助函数调用 } };
这个方案的好处是不用破坏封装性,所有Base的派生类都可以复用这个辅助函数。
方案3:将参数类型改为const C&(仅适用于只处理C对象的场景)
如果你的func只需要接收C类型的对象,可以把参数改成const C&,这样就能调用它的call成员了:
class Base { protected: void call() const {} }; class C : public Base { public: void func(const C& c) { // 参数改为C类型引用 c.call(); // 合法,因为c是C的实例,派生类可以访问其继承的protected成员 } };
注意这个方案有局限性,无法处理其他Base派生类或纯Base对象。
内容的提问来源于stack exchange,提问作者Erik Nouroyan
相关产品推荐
相关产品推荐

