I'm trying to learn SDL using C++. I've created a window.h header and a window.cpp source file for storing a Window class. In window.h it looks something like this:

Class Window {
public:
  Window();
    . . .
private:
  std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> window;
  std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> renderer;
    . . .
}

with some of the code in the class omitted. Then, in my source file, in the definition of the default constructor, I do this:

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);
}

However, when I go to compile, I'm told that unique_ptr [is] constructed with null function pointer deleter, which as far as I can tell is false. Maybe I'm misunderstanding how to use a unique_ptr's deleter, but I cannot figure out what's wrong. Is there something I'm missing or have I completely misunderstood what I'm doing?

有帮助吗?

解决方案

The problem is that in your constructor, you use assignment instead of initialization for the members window and renderer. Your members are implicitly default initialized, which generates an error.

But why is this so and how to change it?

If you're new to C++ this might sound a bit strange, but any class member is initialized before the constructor function body is evaluated. Per default, each member will be initialized with its default constructor, or left uninitialized (if it's a primitive type like int). If you want to change this behavior (i.e. if you want to initialize it with something different, like you want), you have to use the member initializer list.

Example:

Window::Window() :   // <-- put a colon here
    windows(nullptr, SDL_DestroyWindow),     // here comes the member init list
    rendered(nullptr, SDL_DestroyRenderer)
{
}

Note: Since C++11, you can also initialize members at their definition directly (like you can do it in Java for example), but in your case this would make the header look too complex. Also, this wouldn't fit to the rule of encapsulation (in most cases, only the class implementation should know what to do with private members).

其他提示

Use a member initializer list:

Window::Window()
    : windows(nullptr, SDL_DestroyWindow), rendered(nullptr, SDL_DestroyRenderer)
{
    // empty
}

By the time the body of a constructor runs, all members shall already be initialized (default constructed unless you explicitly do something else, like above). Thereafter, you can only assign to them.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top