You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SDL开发中如何在渲染器创建完成后调用Player构造函数传递渲染器

问题本质

你遇到的核心矛盾是C++类成员的初始化顺序规则:Game类的普通成员变量会在进入Game构造函数的函数体之前完成初始化,你写在初始化列表里的player(renderer)执行时,SDL_CreateWindowAndRenderer还没运行,renderer还是空指针,自然无法完成纹理加载。


最优实现方案:使用智能指针存储Player实例

把Game类里的Player成员改为智能指针,等渲染器创建完成后再构造Player对象,既满足你要在Player构造函数里完成所有初始化的需求,也完全符合C++开发规范。

修改步骤:

  1. 修改Game类的player成员声明:
// Game类头文件顶部加#include <memory>
// 把原来的 Player player; 改为
std::unique_ptr<Player> player;
  1. 修改Game构造函数逻辑,删除初始化列表里的player(renderer),等渲染器创建完成后再初始化player:
Game::Game()
{
  SDL_Init(0);
  SDL_CreateWindowAndRenderer(WINDOW_WIDHT, WINDOW_HEIGTH, 0, &window, &renderer);
  SDL_SetWindowTitle(window, "Intento...");

  // 注意:原有判断逻辑存在运算符优先级错误,已经修正
  int imgFlags = IMG_INIT_PNG;
  if (!(IMG_Init(imgFlags) & imgFlags))
  {
    cout << "No se puede inicializar SDL_Img" << endl;
  }
  // 此时renderer已经初始化完成,再调用Player构造函数
  player = std::make_unique<Player>(renderer);
  
  running = true;
  loop();
}
  1. 修复Player类的纹理泄漏问题:
    你现有代码中loadTexture返回的纹理指针没有保存,后续渲染无法使用也无法释放,需要补充成员变量:
class Player
{
  public:
    Player(SDL_Renderer *renderer);
    // 析构函数销毁纹理避免泄漏
    ~Player() {
        if (texture) SDL_DestroyTexture(texture);
    }
    // 省略其他原有方法声明
  private:
    SDL_Rect dest;
    SDL_Rect src;
    // 新增纹理成员变量
    SDL_Texture* texture = nullptr;
};

// 修改Player构造函数保存返回的纹理
Player::Player(SDL_Renderer *renderer){
  texture = loadTexture("mario.png", renderer);
  // 后续原有初始化逻辑
}

替代方案:两步初始化

如果不想使用指针,也可以给Player添加默认构造函数和单独的init方法,等渲染器创建完成后调用player.init(renderer)完成纹理加载。这种方案并非不符合规范,很多游戏开发框架中都会用两步初始化来规避资源依赖顺序问题,只需要额外做逻辑判断保证init只会被调用一次即可。


内容的提问来源于stack exchange,提问作者Hernán Garcia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 10:54:02