I am trying to implement graphic objects that can be either Sprite, Base, Point or some others, but not very many types at all. That's why I do not make separate classes. All types exist in 1 class due to unions and few short switches. I use directly objects, not pointers, and no virtual methods.The question is also, do you agree that it's a good idea to mark everything inline in this particular case.In this exact code, unions don't look useful as the code is raw and classes unfinished.Declarations:#ifndef GFX_HPP_INCLUDED#define GFX_HPP_INCLUDED#include <vector>namespace keng {class gfx {public: // types    enum types {        sprite,        base,        point    };    static const int base_default_size = 10;private: // default base    static gfx* const default_base;public: // special construct methods    static gfx* create_sprite(        int position = 0,        int map = 0,        int x = 0,        int y = 0,        float scale = 1.0f,        gfx* base = default_base    );    static gfx* create_base(        int position = 0,        int size = 0,        float scale = 1.0f,        gfx* base = default_base    );    static gfx* create_point(        int position = 0,        int x = 0,        int y = 0,        float scale = 1.0f,        gfx* base = default_base    );public: // switching methods    void render();    ~gfx();private: // untitled special constructors    // sprite    gfx(        int map,        int x,        int y,        float scale    );    // base    gfx(        int size,        float scale    );    // point    gfx(        int x,        int y,        float scale    );private: // help    typedef std::vector<std::vector<gfx>> gfx_container_t;    template<typename... Args>    static gfx* construct(gfx* base, int position, Args... args);private: // type data    int type;private: // switching data  union {    int map; // sprite    gfx_container_t* gfx_container; // base  };  union {    int x; // sprite / point  };  union {    int y; // sprite / point  };  union {    float scale; // sprite / base / point  };  union {    int map_x; // sprite  };  union {    int map_y; // sprite  };  union {    bool mirror_x; // sprite  };  union {    bool mirror_y; // sprite  };}; // class gfx} // namespace keng#include gfx.hh#endif // GFX_HPP_INCLUDEDDefinitions:#ifndef GFX_HH_INCLUDED#define GFX_HH_INCLUDED#include spriteset.hppusing namespace keng;// default gfxgfx* const gfx::default_base = new gfx(base_default_size, 1.0f);// special construct methodsinline gfx* gfx::create_sprite(    int position,    int map,    int x,    int y,    float scale,    gfx* base){    return construct(        base,        position,        map,        x,        y,        scale    );}inline gfx* gfx::create_base(    int position,    int size,    float scale,    gfx* base){    return construct(        base,        position,        size,        scale    );}inline gfx* gfx::create_point(    int position,    int x,    int y,    float scale,    gfx* base){    return construct(        base,        position,        x,        y,        scale    );}// switching methodsinline void gfx::render() {    switch (type) {        case sprite:        {            int vertex_x1 = mirror_x * Spriteset::width[map];            int vertex_x2 = (1 - mirror_x) * Spriteset::width[map];            int vertex_y1 = mirror_y * Spriteset::height[map];            int vertex_y2 = (1 - mirror_y) * Spriteset::height[map];            GLfloat texture_x1 = Spriteset::normed_width[map] * map_x;            GLfloat texture_x2 = texture_x1 + Spriteset::normed_width[map];            GLfloat texture_y1 = Spriteset::normed_height[map] * map_y;            GLfloat texture_y2 = texture_y1 + Spriteset::normed_height[map];            glEnable(GL_TEXTURE_2D);            glBindTexture(GL_TEXTURE_2D, Spriteset::texture[map]);            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);            glBegin(GL_POLYGON);                glTexCoord2f(texture_x1, texture_y1);                glVertex2f(vertex_x1, vertex_y1);                glTexCoord2f(texture_x1, texture_y2);                glVertex2f(vertex_x1, vertex_y2);                glTexCoord2f(texture_x2, texture_y2);                glVertex2f(vertex_x2, vertex_y2);                glTexCoord2f(texture_x2, texture_y1);                glVertex2f(vertex_x2, vertex_y1);            glEnd();            glDisable(GL_TEXTURE_2D);            break;        }        case base:            for (std::vector<gfx>& vg : *gfx_container)                for (gfx& g : vg)                    g.render();            break;        case point:            glColor4f(1.0f, 1.0f, 1.0f, 1.0f);            glBegin(GL_POINTS);                glVertex2f(.0f, .0f);            glEnd();            break;    }}inline gfx::~gfx() {    switch (type) {        case sprite:            break;        case base:            delete gfx_container;            break;        case point:            break;    }}// untitled special constructorsinline gfx::gfx(    int map,    int x,    int y,    float scale):    type(sprite),    map(map),    x(x),    y(y),    scale(scale){}inline gfx::gfx(    int size,    float scale):    type(base),    gfx_container(new gfx_container_t(size)),    scale(scale){}inline gfx::gfx(    int x,    int y,    float scale):    type(point),    x(x),    y(y),    scale(scale){}// helptemplate<typename... Args>inline gfx* gfx::construct(gfx* base, int position, Args... args) {    gfx* result = new gfx(args...);    (*base->gfx_container)[position].push_back(*result);    return result;}#endif // GFX_HH_INCLUDED
Graphic object class
c++;game;graphics;opengl