我看到了一些关于这个主题的话题,但我真的不明白......
有足够的病人告诉我如何才能使这个构造函数正确?
SdlManager::SdlManager() {
//SDL init
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "Could not initialize SDL: " << SDL_GetError() << std::endl;
goto error1;
}
//Init mutex for SDL access
m_mutex = SDL_CreateMutex();
if (m_mutex == nullptr)
goto error2;
try {
m_display = DisplayManager(m_mutex, false);
m_events = EventManager(m_mutex);
}
catch (void* _) {
goto error3;
}
return;
//Error Handling
error3:
SDL_DestroyMutex(m_mutex);
error2:
SDL_Quit();
error1:
throw ;
}
欢迎任何建议。
由于 祝你有愉快的一天。
编辑:
关于错误:
src/sdl_manager.cpp:6:1: error: uninitialized reference member in ‘class sdl::DisplayManager&’ [-fpermissive]
SdlManager::SdlManager() {
^
In file included from src/sdl_manager.cpp:2:0:
./src/include/sdl_manager.hpp:13:20: note: ‘sdl::DisplayManager& sdl::SdlManager::m_display’ should be initialized
DisplayManager& m_display;
^
src/sdl_manager.cpp:6:1: error: uninitialized reference member in ‘class sdl::EventManager&’ [-fpermissive]
SdlManager::SdlManager() {
^
In file included from src/sdl_manager.cpp:2:0:
./src/include/sdl_manager.hpp:14:19: note: ‘sdl::EventManager& sdl::SdlManager::m_events’ should be initialized
EventManager& m_events;
^
似乎我的try-catch块不好
EDIT2:
我只是放了sdl_manager.hpp。
#ifndef SDL_MANAGER_HPP
#define SDL_MANAGER_HPP
#include <SDL2/SDL_mutex.h>
#include "display_manager.hpp"
#include "event_manager.hpp"
namespace sdl
{
class SdlManager {
private:
SDL_mutex* m_mutex;
DisplayManager& m_display;
EventManager& m_events;
public:
SdlManager();
~SdlManager();
};
}
#endif
答案 0 :(得分:2)
所以,这不是现代惯用的C ++的样子,这就是它令人困惑的原因。
基本上在上面的代码中,您使用的是“goto”而不是使用析构函数。这就是基于RAII习惯用语的代码。
struct Sdl_error : public std::exception {
...
};
struct Sdl_Init_RAII {
Sdl_Init_RAII()
{
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cout << "Could not initialize SDL: " << SDL_GetError() << std::endl;
throw Sdl_error();
}
}
~Sdl_Init_RAII()
{
SDL_Quit();
}
};
struct Sdl_Mutex {
SDL_Mutex * m_ptr;
Sdl_Mutex()
: m_ptr(SDL_CreateMutex())
{
if (m_ptr == nullptr) throw Sdl_error();
}
~Sdl_Mutex()
{
if (m_ptr) { SDL_DestroyMutex(m_ptr); }
}
};
SdlManager::SdlManager
: m_init()
, m_mutex()
, m_displayer(m_mutex.m_ptr, false)
, m_events(m_mutex.m_ptr)
{}
请注意,您更改了一点点发布的代码示例,但是您应该将Sdl_Init_RAII
m_init
类型的成员添加到SdlManager
,以便上面的代码剪切有意义。< / p>
请注意,SdlManager不需要在这里使用析构函数,因为它本身不直接管理任何C资源。但是,显示,事件,互斥都是如此。并且Sdl_Init_RAII也存在,即使它没有成员变量 - 它的目的是强制执行合同,每当我们调用C函数SDL_Init时我们也稍后调用SDL_Quit。每当你有一个C lib强加某些要求时,通常最好使用RAII对象来确保你的C ++程序符合要求。
编辑:现在您已经专门发布了错误消息,我可以看到我的重构也将修复它。问题是,当你有一个带有成员变量的构造函数作为引用时,你必须在initalizer列表中初始化它,否则它不能绑定到函数开头的任何东西(!),语言只是不允许这样做,禁止这就是整个参考点。
答案 1 :(得分:1)
错误uninitialized reference member
表示您已将m_display
和m_events
声明为引用。这些必须在构造函数的初始化列表中初始化,如下所示:
SdlManager::SdlManager(DisplayManager& display, EventManager& events)
: m_mutex(nullptr)
, m_display(display)
, m_events(events)
{
...
}