装饰器模式实现:派生类无法访问基类保护成员的问题求助
问题原因
C++中protected成员的访问权限有明确限制:派生类仅能访问自身对象中的基类子对象的protected成员,或者同类型派生类对象的基类子对象的protected成员。你的代码中B::func2()里调用的是a->func(),这里的a是一个独立的A实例指针,并非B自身继承的A子对象,因此编译器会判定为非法访问。
解决方案
以下是几种无需频繁修改基类A的实现方式:
方案1:给基类添加public封装接口
在A中新增一个public成员函数,封装对protected成员func()的调用。这是最符合开闭原则的方案,后续新增装饰器类无需再修改A。
#include <iostream> class A { protected: void func() { std::cout << "func ran\n"; } public: // 新增public接口,封装对func的调用 void execute_func() { func(); } }; class B : public A { public: void func2() { a->execute_func(); } A* a; }; int main() { A a; B b; b.a = &a; b.func2(); }
方案2:给基类添加protected辅助函数
如果不想暴露func()的public接口,可以在A中新增一个protected的辅助函数,允许派生类调用任意A实例的func()。只需修改一次A,后续所有派生装饰器都可以复用这个辅助函数。
#include <iostream> class A { protected: void func() { std::cout << "func ran\n"; } // 新增protected静态函数,允许派生类操作任意A实例 static void invoke_func(A* instance) { instance->func(); } }; class B : public A { public: void func2() { invoke_func(a); } A* a; }; int main() { A a; B b; b.a = &a; b.func2(); }
方案3:调整装饰器的继承与持有关系
装饰器模式的标准设计中,装饰器和被装饰对象应继承同一个抽象基类。如果你可以将A设计为抽象类,让被装饰对象和装饰器都实现这个抽象接口,那么可以通过抽象接口的public方法来调用功能,从根源上避免protected访问问题。
#include <iostream> // 抽象基类(组件) class Component { public: virtual void do_func() = 0; virtual ~Component() = default; }; // 具体组件 class A : public Component { protected: void func() { std::cout << "func ran\n"; } public: void do_func() override { func(); } }; // 装饰器 class B : public Component { private: Component* component; public: B(Component* comp) : component(comp) {} void do_func() override { // 可以添加装饰逻辑,再调用原组件的方法 component->do_func(); } }; int main() { Component* a = new A(); Component* b = new B(a); b->do_func(); delete b; delete a; }
这种方案更贴合装饰器模式的设计初衷,同时彻底解决了访问权限问题,扩展性也更好。
内容的提问来源于stack exchange,提问作者kasra
相关产品推荐
相关产品推荐

