使用装饰器模式时基类无默认构造函数的构造函数错误修复咨询
修复C++装饰器模式中基类无默认构造函数的初始化错误
你遇到的这个错误是C++里很常见的初始化问题,根源其实很清晰:你的Game类因为定义了带参数的构造函数Game(int a),编译器会自动取消生成它的无参默认构造函数。而当子类Decorator被实例化时,编译器会尝试自动调用基类的默认构造函数来初始化基类部分,但这个构造函数不存在,所以直接抛出了错误。
下面给你两种可行的修复方案,第二种更贴合装饰器模式的设计规范:
方案1:显式调用基类的带参构造函数
既然Game没有默认构造,那我们必须在Decorator的构造初始化列表里,手动指定基类Game的构造方式。因为Game的a是protected成员,子类可以直接访问被装饰对象的a值,你可以复用这个值来初始化基类:
class Decorator : public Game{ Game *m_game; public: // 显式调用Game(int a)构造函数,传入被装饰对象的a值 Decorator(Game *game) : Game(game->a), m_game(game) {} };
如果你不需要复用被装饰对象的a,也可以传入自定义的固定值(比如Game(0)),只要符合Game构造函数的参数要求就行。
方案2:调整装饰器模式的实现(更符合设计规范)
在标准的装饰器模式中,我们通常会让Game作为抽象基类(包含纯虚函数),装饰器的核心是持有被装饰对象并转发调用,这样基类的初始化逻辑会更合理,也能更好地实现动态扩展功能的目的:
// 抽象基类:定义游戏的核心行为 class Game { protected: int a; public: virtual ~Game() = default; // 必须声明虚析构,确保子类析构正确 Game(int a) : a(a) {} // 纯虚函数,强制子类实现核心逻辑 virtual void play() = 0; }; // 具体游戏类:实现真实的游戏逻辑 class ConcreteGame : public Game { public: ConcreteGame(int a) : Game(a) {} void play() override { // 示例逻辑 std::cout << "Playing concrete game with a = " << a << std::endl; } }; // 基础装饰器类:继承Game并持有被装饰对象 class Decorator : public Game { protected: Game* m_game; // 设为protected,方便子类装饰器访问 public: Decorator(Game* game) : Game(game->a), m_game(game) {} // 转发play调用给被装饰对象 void play() override { m_game->play(); } }; // 示例装饰器:给游戏添加音效功能 class SoundDecorator : public Decorator { public: SoundDecorator(Game* game) : Decorator(game) {} void play() override { m_game->play(); // 添加额外功能 std::cout << "Playing background music..." << std::endl; } };
额外提醒:记得管理好m_game的内存,避免内存泄漏。如果装饰器负责销毁被装饰对象,可以在Decorator的析构函数里添加delete m_game;,或者使用std::unique_ptr<Game>这类智能指针来自动管理内存。
内容的提问来源于stack exchange,提问作者hhw h
相关产品推荐
相关产品推荐

