构造函数中的异常
Exception in constructor
我看过一些关于这个主题的话题,但是我真的不明白…
有足够的耐心告诉我如何才能使这个构造函数正确?
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
所以,这不是现代习惯的c++的样子,这就是为什么它令人困惑的原因。
- 不要使用"goto",这里绝对没有理由。
- 使用RAII习语来简化这些东西。
基本上在上面的代码中,你使用"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)
{}
请注意,您稍微更改了代码示例,但是您应该在SdlManager
中添加一个名为m_init
的Sdl_Init_RAII
类型的成员,以便上述代码片段有意义。
注意SdlManager不需要在这里有析构函数,因为它本身不直接管理任何C资源。但是,显示,事件,互斥都是这样。而且Sdl_Init_RAII也存在,即使它没有成员变量——它的目的是强制执行合约,无论何时我们调用C函数SDL_Init,我们稍后也会调用SDL_Quit。当你有一个C库强加了一些这样的要求时,使用RAII对象来确保你的c++程序符合要求通常是一个好主意。
编辑:既然你特别发布了错误信息,我可以看到我的重构也会修复它。问题是,当你有一个成员变量是引用的构造函数时,你必须在初始化列表中初始化它,否则它不能绑定到函数开头的任何东西(!),语言根本不允许这样做,禁止这是引用的整个点。
错误uninitialized reference member
表示您声明了m_display
和m_events
作为引用。这些必须在构造函数的初始化列表中初始化,如下所示:
SdlManager::SdlManager(DisplayManager& display, EventManager& events)
: m_mutex(nullptr)
, m_display(display)
, m_events(events)
{
...
}
相关文章:
- 从构造函数抛出异常时如何克服内存泄漏
- 如何编写带有异常的构造函数
- 从 C++ 中异常的构造函数引发异常
- 我正在尝试创建一个使用 c++ 中的参数包构造函数的异常类
- 稍后在构造函数中重新启动异常指令删除此指令
- 自定义异常中的用户定义的空构造函数,具有多个继承和抽象基类
- 构造函数中引发的异常
- 如何捕获源自静态分配对象的构造函数的异常?
- 从构造函数内存泄漏引发异常
- C++:如何捕获构造函数引发的异常?
- std::vector::emplace() 真的在面对抛出移动构造函数/赋值运算符时提供了强大的异常保证吗?
- V8 - 节点C++插件 - 在构造函数中引发异常会导致"致命错误:v8::ToLocalChecked Em
- 为什么要抛出引用调用复制构造函数的异常?
- std::vector 默认构造函数可以抛出异常吗?
- 如何防止构造函数在引发异常时创建对象
- 当构造函数的参数类型错误时引发异常
- 异常构造函数中的例外
- C++11 引入了采用 'const char*' 的异常构造函数.但是为什么
- 在异常构造函数中参数化错误消息是一种好的做法吗
- 异常构造函数来填充字符串流