如何实现游戏引擎库对用户自定义application子类实例的访问?
实现方案:自动注册式游戏实例获取
核心思路
把实例注册逻辑封装到引擎基类中,让用户的子类在定义时自动完成注册,无需手动编写get_game这类繁琐的桥接函数。
引擎端实现代码
1. 引擎头文件(engine.h)
#include <memory> namespace engine { class application { protected: // 全局唯一的游戏实例指针 static inline std::unique_ptr<application> s_game_instance; // 构造函数设为protected,防止直接实例化基类 application() = default; public: virtual ~application() = default; // 引擎启动入口,直接运行游戏实例 static void run() { if (!s_game_instance) { // 触发子类的自动注册逻辑 register_game_instance(); } // 引擎主循环示例 while (true) { s_game_instance->update(); s_game_instance->render(); } } // 用户子类必须实现的纯虚方法 virtual void update() = 0; virtual void render() = 0; private: // 占位函数,用于触发模板实例化逻辑 static void register_game_instance(); }; // 自动注册模板,子类通过该模板完成实例注册 template<typename T> struct game_registrar { game_registrar() { // 将子类实例绑定到全局指针 application::s_game_instance = std::make_unique<T>(); } }; // 简化注册的宏,用户只需一行代码完成注册 #define DECLARE_GAME(GameClass) \ static engine::game_registrar<GameClass> g_game_registrar; }
2. 引擎源文件(engine.cpp)
#include "engine.h" namespace engine { // 实现占位函数,确保编译时模板能被正确实例化 void application::register_game_instance() {} }
用户端使用方式
用户仅需定义继承自engine::application的游戏类,再通过宏完成注册即可,无需额外编写实例获取逻辑:
#include "engine.h" class my_game : public engine::application { public: void update() override { // 游戏更新逻辑 } void render() override { // 游戏渲染逻辑 } }; // 自动注册游戏类,程序启动时会创建实例并绑定到引擎 DECLARE_GAME(my_game) // 用户入口函数,直接调用引擎启动方法 int main() { engine::application::run(); return 0; }
原理说明
- 当用户使用
DECLARE_GAME(my_game)时,会生成一个全局的game_registrar<my_game>对象,该对象在程序启动阶段(main函数执行前)完成初始化。 - 初始化过程中,
game_registrar的构造函数会将my_game的实例赋值给引擎基类中的全局指针s_game_instance。 - 引擎调用
run方法时,直接使用已初始化的全局实例,完全无需用户手动处理实例创建和暴露逻辑。
优势对比
- 彻底解决了原
extern方案中需要手动编写桥接函数、处理头文件声明的繁琐问题,用户代码量大幅减少。 - 全局注册在程序启动时自动完成,引擎可直接访问唯一的游戏实例,符合单例模式的需求。
内容的提问来源于stack exchange,提问作者ignatz
相关产品推荐
相关产品推荐

