我正在尝试使用C ++学习SDL。我创建了一个window.h
标头和一个window.cpp
源文件,用于存储Window类。在window.h
中,它看起来像这样:
Class Window {
public:
Window();
. . .
private:
std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> window;
std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> renderer;
. . .
}
省略了类中的一些代码。然后,在我的源文件中,在默认构造函数的定义中,我这样做:
Window::Window() {
window = std::unique_ptr<SDL_Window, void (*)(SDL_Window*)>(nullptr, SDL_DestroyWindow);
renderer = std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)>(nullptr, SDL_DestroyRenderer);
}
然而,当我去编译时,我被告知unique_ptr [is] constructed with null function pointer deleter
,据我所知,这是假的。也许我误解了如何使用unique_ptr
的删除器,但我无法弄清楚出了什么问题。有什么我想念的东西,或者我完全误解了我在做什么?
答案 0 :(得分:5)
问题在于,在构造函数中,您对成员window
和renderer
使用分配而不是初始化。您的成员默认默认初始化,这会产生错误。
但为什么会如此以及如何改变呢?
如果您是C ++的新手,这可能听起来有点奇怪,但在评估构造函数体之前,任何类成员都已初始化。默认情况下,每个成员将使用其默认构造函数进行初始化,或者保持未初始化(如果它是int
之类的基本类型)。如果你想改变这种行为(即如果你想用不同的东西初始化它,就像你想要的那样),你必须使用member initializer list。
示例:
Window::Window() : // <-- put a colon here
windows(nullptr, SDL_DestroyWindow), // here comes the member init list
rendered(nullptr, SDL_DestroyRenderer)
{
}
注意:从C ++ 11开始,您也可以initialize members at their definition directly(就像您可以在Java中一样),但在您的情况下,这会使标题看起来过于复杂。此外,这不适合封装规则(在大多数情况下,只有类实现应该知道如何处理私有成员)。
答案 1 :(得分:1)
使用成员初始化列表:
Window::Window()
: windows(nullptr, SDL_DestroyWindow), rendered(nullptr, SDL_DestroyRenderer)
{
// empty
}
当构造函数的主体运行时,所有成员都应该已经初始化(默认构造除非你明确地做其他事情,如上所述)。此后,您只能分配给他们。