问题
This is a continuation of my previous post. Since it has already been closed I decided to make a new post. I removed half of the code to make it more readable.
Some of the posts I read:
Smart pointers with SDL
Is it possible to use SDL2 with smart pointers?
Couple of questions about SDL_Window and unique_ptr
class cGraphics
{
public:
// Creator functions
std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> Create_Window(int xWin, int yWin);
// ctor & dtor
cGraphics() : m_Window(nullptr, SDL_DestroyWindow) {}
cGraphics(int xWin, int yWin);
~cGraphics();
private:
std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> m_Window;
};
cGraphics::cGraphics(int xWin, int yWin)
{
m_Window = std::move(Create_Window(xWin, yWin));
if (m_Window == nullptr)
{
throw "SDL_Window or SDL_Renderer not ready!";
}
}
cGraphics::~cGraphics()
{
IMG_Quit();
SDL_Quit();
}
std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> cGraphics::Create_Window(int xWin, int yWin)
{
return std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)>(SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, xWin, yWin, SDL_WINDOW_SHOWN), SDL_DestroyWindow);
}
The compiler complains that:
'std::unique_ptr<SDL_Window,void (__cdecl *)(SDL_Window *)>::unique_ptr': no appropriate default constructor available
I understand that this error usually shows up when the compiler cannot locate a default constructor for some of the members. However this is not true as I explicitly declared a default value for the std::unique_ptr
.
If the compiler is actually complaining about SDL_Window
, which is an incomplete type (a C struct), what can I do about this?
回答1:
A std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)>
is not default constructable. That means in
cGraphics::cGraphics(int xWin, int yWin) ***
{
m_Window = std::move(Create_Window(xWin, yWin));
if (m_Window == nullptr)
{
throw "SDL_Window or SDL_Renderer not ready!";
}
}
When you reach the part ***
the compiler is going to try and default construct m_Window
since you didn't do so in the member initialization list. That attempt from the compiler ro default construct m_Window
is what causes the error. We can fix this by moving m_Window = std::move(Create_Window(xWin, yWin));
out of the constructor body and putting it in the member initialization list like
cGraphics::cGraphics(int xWin, int yWin) : m_Window(Create_Window(xWin, yWin))
{
if (m_Window == nullptr)
{
throw "SDL_Window or SDL_Renderer not ready!";
}
}
If you don't want to do that then you can delegate to the default constructor and then assign to m_Window
like you were doing originally. That would look like
cGraphics::cGraphics(int xWin, int yWin) : cGraphics()
{
m_Window = Create_Window(xWin, yWin);
if (m_Window == nullptr)
{
throw "SDL_Window or SDL_Renderer not ready!";
}
}
回答2:
Here is how you defined your unique_ptr
:
std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> m_Window;
That means, it's constructor has to be called with an instance of the custome deleter, in your case, function SDL_DestroyWindow
- remember, you told the pointer what is deleter's type, not what the actual deleter (a function pointer in your case).
To make this code work, you have to properly construct your pointer with a deleter instance, for example:
cGraphics::cGraphics(int xWin, int yWin) :
m_Window{Create_Window(xWin, yWin)} {...}
来源:https://stackoverflow.com/questions/50956579/no-appropriate-default-constructor-available-for-stdunique-ptr