2

I'm fairly inexperienced with C++ and I keep seeing this pattern in the header files of the graphics library wrappers within the code base that I'm trying to learn from; could somebody explain to me what the first eight lines in the 'public' section are doing?

Full code:

#pragma once

#include <glad/glad.h>
#include "textures.h"

namespace gl {
    class Framebuffer final {
      public:
        Framebuffer();
        ~Framebuffer();

        Framebuffer(Framebuffer&& other);
        Framebuffer& operator=(Framebuffer&& other);

        Framebuffer(const Framebuffer&) = delete;
        Framebuffer& operator=(const Framebuffer&) = delete;

        void create(unsigned int width, unsigned int height);
        void destroy();

        void bind() const;

        void bindTexture() const;

      private:
        void reset();

        Texture2d m_texture;
        GLuint m_handle = 0;
        GLuint m_renderbufferHandle = 0;

        unsigned m_width = 0;
        unsigned m_height = 0;
    };

    void unbindFramebuffers(unsigned windowWidth, unsigned windowHeight);
}

The lines I'm curious about:

namespace gl {
    class Framebuffer final {
      public:
        Framebuffer();
        ~Framebuffer();

        Framebuffer(Framebuffer&& other);
        Framebuffer& operator=(Framebuffer&& other);

        Framebuffer(const Framebuffer&) = delete;
        Framebuffer& operator=(const Framebuffer&) = delete;

Including these lines causes my build to fail with an unresolved external symbol error, however removing them also causes the build to fail for different unresolved symbol reasons. I assume it's trying to add, overwrite, or extend something in the 'gl' namespace? But I'm not sure about the specifics of what it's trying to accomplish are.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Tucker S
  • 23
  • 3
  • 4
    First, there is declaration of default constructor and destructor. (The implementation is surely in the corresponding C++ source.) Then, there follow the declaration of move constructor and move assignment (which are also defined in the C++ source.) Then, the copy constructor and assignment are deleted because they wouldn't work properly, and the author intended to make sure that they are not called (accidentally) without getting a compiler complaint (error). FYI: [The rule of three/five/zero](https://en.cppreference.com/w/cpp/language/rule_of_three) – Scheff's Cat Aug 21 '20 at 08:45
  • 4
    For the general purpose of constructors/destructors, please, use your C++ book of choice. These are fundamental parts of the language - they should be mentioned in any. – Scheff's Cat Aug 21 '20 at 08:48
  • 1
    Concerning _Including these lines causes my build to fail with an unresolved external symbol error, however removing them also causes the build to fail for different unresolved symbol reasons._ You missed to add the corresponding source or library to your project (or compile command) where the implementation of this class is provided in. FYI: [SO: What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/q/12573816/7478597) – Scheff's Cat Aug 21 '20 at 08:52

1 Answers1

3

these are special members of the class. Let's check it out,

Framebuffer();

This is a default constructor that creates an object without any argument. Actually, it is written by the compiler like this with a member initializer list.

Framebuffer() : m_handle{0}, m_renderbufferHandle{0}, m_width{0}, m_height{0} {};

If the m_texture variable has not any initial value from Texture2D that will start with a garbage value.

The next function is

~Framebuffer();

it is called a destructor. It is responsible to terminate the initialized variable. For instance, you have allocated memory via malloc function. When the instance, which is created from Framebuffer class, it needs to free that memory to avoid memory leakage.

The next two one is move semantics. The first one is move constructor, the other one is move assignment.

Framebuffer(Framebuffer&& other);
Framebuffer& operator=(Framebuffer&& other);

So, what is the move semantics? It steals resources of the object, which is a lifetime is done. You can think that there is an object, which will be terminated, but you want to use their values. Instead of coping its variables, you take its memory place etc. For example, you create a temporary object like;

Framebuffer fm = Framebuffer{};

in this code will call move constructor. To call move assignment you need to write something like that;

Framebuffer fm;
fm = Framebuffer{};

This is move assignment.

The other two one is copy semantics, but they have been deleted.

Framebuffer(const Framebuffer&) = delete;
Framebuffer& operator=(const Framebuffer&) = delete;

So, if you write code that calls copy special members the compiler will raise a syntax error. Thus, you cannot write like this;

Framebuffer fm;
Framebuffer myfm;
Framebuffer dummyfm{fm}; // syntax error
fm = myfm; // syntax error

It copies all of the variables of an object. Also, if there is memory allocation, it allocates new memory and copies from other objects. Please refer for detailed explanation check;

https://en.cppreference.com/w/cpp/language/classes

Also, you can watch from Howard Hinnant presentation;

https://www.youtube.com/watch?v=vLinb2fgkHk

Murat Hepeyiler
  • 430
  • 3
  • 12