Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delay initializing a member variable

Tags:

c++

I have class defined like so:

class GlslProgram
{
public:
    class Format {
    public:
        Format& vertex(const char* shader_path);
        std::string m_vertex_shader;

    private:
        std::string load_shader(const char* shader_path);
    };

    void use() const;
    void uniform(const GLchar* name, const GLboolean value) const;


    GlslProgram() {};
    GlslProgram(const Format& format, const bool separable = false);

private:
    GLuint m_handle;
    GLuint compile_shader(const std::string shader_string, const GLenum 
};

The second constructor (i.e. GlslProgram(const Format& format, const bool separable = false); is the only one I want to use or have be available.

I want to delete the default constructor (or make it private) however I can't because I have to declare (uninitialized) instances of GlslProgram as members of another class in my application.

i.e.

class BasicCubeExample : public Application
{
private:
    virtual void set_info()
    {
        Application::set_info();    
        m_info.title = "Basic cube example";
    }
    // Here the format is not yet known so I can not call the correct constructor (at this time)
    GlslProgram m_shader;
};

So, by declaring GlslProgram m_shader; I both call the default constructor of GlslProgram (which I do not want to do) and I have to keep the default constructor available (which I do no want to do).

How can I declare an instance of a class as a member variable without calling its default constructor?

like image 796
Startec Avatar asked Oct 27 '25 15:10

Startec


1 Answers

One solution (mentioned in comments and another answer) is to allocate the program in BasicCubeExample dynamically and hold it by a smart pointer.

There is also an alternative which avoids dynamic allocation, namely std::optional (or, before C++17, boost::optional):

class BasicCubeExample : public Application
{
private:
    virtual void set_info()
    {
        Application::set_info();    
        m_info.title = "Basic cube example";
    }
    // Here the format is not yet known so I can not call the correct constructor (at this time)
    std::optional<GlslProgram> m_shader;
};

Later, initialise it like this:

m_shader.emplace(format, separable);

In usage afterwards, optional is dereferenced just like a pointer, using *m_shader or m_shader->something.

like image 157
Angew is no longer proud of SO Avatar answered Oct 29 '25 06:10

Angew is no longer proud of SO