How to correctly manage initialisation in constructor?

  abstraction, c++, glew, glfw, opengl

I’m writing a simple wrapper in C++ around GLFW and OpenGL, as an exercice. I have a class Window and a class Renderer. The Window class owns a Renderer member.

Window sets the GLFW context in its constructor and run the main loop, and call for its Renderer member to draw. Renderer sets the buffers in its constructor, and does the OpenGL things.

The problem I’ve got is that OpenGL calls require to have an OpenGL context available. If I were to just initialise the Renderer before calling the constructor of Window, the constructor of Renderer would be called before the GLFW context would be created.

What I did is that I instead store a unique_ptr to a Renderer in Window, and I call std::make_unique<Renderer> in the constructor of Window. Then, in the destructor, I call std::unique_ptr::reset() before destroying the GLFW context, so that I can make the OpenGL calls to free stuff with a still valid context.

class Window
{
   public:
       Window()
       {
           //initialising GLFW and creating an OpenGL context
           //...
           m_renderer = std::make_unique<Renderer>();
       }
       ~Window()
       {
           m_renderer.reset();
           glfwTerminate();
       }
       int run()
       {
           while(...)
           {
               m_renderer->draw();
               //...
           }
           return 0;
       }
   private:
       std::unique_ptr<Renderer> m_renderer; 
       //...
}

class Renderer
{
    public:
        Renderer() { //Set buffers }
        ~Renderer() { //Free buffers }
        draw() { glDrawElements(...); //... }
    private:
        //...
}

int main()
{
     Window window();
     return window->run();
}
        

I understand that object should already be initialised in the body of the constructor, which is not the case here. I feel I might have done some dependency between Renderer and Window backwards or that my general architecture is wrong. I would rather rely on the constructor and destructors being called at the right moment based on the scope and not on me manually triggering it.

What would be a better solution?

Source: Windows Questions C++

LEAVE A COMMENT