如何延迟成员变量的初始化

时间:2018-01-05 07:52:39

标签: c++

我有一个像这样定义的java类:

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

第二个构造函数(即GlslProgram(const Format& format, const bool separable = false);是我唯一想要使用或可用的构造函数。

我想删除默认构造函数(或将其设为私有)但是我不能因为我必须在我的应用程序中声明(未初始化)GlslProgram实例作为另一个类的成员。

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

因此,通过声明GlslProgram m_shader;我同时调用GlslProgram的默认构造函数(我不想这样做)并且我必须保持默认构造函数(我不想这样做) )。

如何在不调用默认构造函数的情况下将类的实例声明为成员变量?

3 个答案:

答案 0 :(得分:4)

一个解决方案(在评论和另一个答案中提到)是动态地在BasicCubeExample中分配程序并通过智能指针保存它。

还有一种避免动态分配的替代方案,即std::optional(或者,在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;
};

稍后,将其初始化为:

m_shader.emplace(format, separable);

在使用之后,使用optional*m_shaderm_shader->something取消引用,就像指针一样。

答案 1 :(得分:1)

您可以将成员m_shader声明为指针,以便可以在以后初始化它。

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

在以后的阶段初始化:

m_shader = new GlslProgram(.... arguments);

您必须在BasicCubeExample类的析构函数中取消分配内存,如下所示。

BasicCubeExample::~BasicCubeExample()
{
    delete m_shader;
}

更好的选择是使用智能指针,这样您就不必担心解除分配。声明m_shader如下:

std::unique_ptr<GlslProgram> m_shader;

答案 2 :(得分:0)

您实际上可以在初始化列表中调用正确的构造函数:

BasicCubeExample() : m_shader(GlslProgram(format, separable)) {};