【问题标题】:Member Object That Cannot Be Instantiated Upon Declaration声明时无法实例化的成员对象
【发布时间】:2019-09-13 11:48:23
【问题描述】:

这是一个Mesh类:

// Mesh.h

class Mesh
{
   std::array<float, 144> m_CanvasVertices;
   std::array<unsigned short, 36> m_CanvasIndices;
   std::array<float, 24>  m_SquareVertices;
   std::array<unsigned short, 6> m_SquareIndices;
   std::array<glm::vec2, 32> m_SquareOffsets;
   Buffers::VertexBuffer* Canvas_VBO;
public:
   Mesh();
   void InitialiseMembers();
};

// Mesh.cpp:

Mesh::Mesh()
: m_CanvasVertices(), m_CanvasIndices(), m_SquareVertices(),
  m_SquareIndices(), m_SquareOffsets(), Canvas_VBO()
{
    InitialiseMembers();

    Buffers::VertexBuffer aVBO(m_CanvasVertices);
    Canvas_VBO = &aVBO;
}

void Mesh::InitialiseMembers()
{
    m_CanvasVertices = { ... }; 
    m_CanvasIndices = { ... };
    m_SquareVertices = { ... };
    m_SquareIndices = { ... };
    m_SquareOffsets = { ... };
}

这是一个VertexBuffer类:

class VertexBuffer
{
    unsigned int m_VBO;
public:
    template<typename T, unsigned short int N>
    VertexBuffer(const std::array<T, N>& data, int draw_method = GL_STATIC_DRAW)
        : m_VBO(0)
    {
        GLFunctionCall(glGenBuffers(1, &m_VBO));
        GLFunctionCall(glBindBuffer(GL_ARRAY_BUFFER, m_VBO));
        if (draw_method == GL_STATIC_DRAW)
        {
            GLFunctionCall(glNamedBufferData(m_VBO, sizeof(data), &data, draw_method));
        }
        else if (draw_method == GL_DYNAMIC_DRAW)
        {
            GLFunctionCall(glNamedBufferData(m_VBO, sizeof(data), &data, draw_method));
        }
    }

    template<typename T, unsigned short int N>
    void UpdateDynamicData(std::array<T, N>& data) const
    {
        GLFunctionCall(glNamedBufferData(m_VBO, sizeof(data), &data, GL_DYNAMIC_DRAW));
    }

    ~VertexBuffer();
    void Bind() const;
    void Unbind() const;
    unsigned int GetBufferID() const;
};

我想在我的 Mesh 类中创建一个 VertexBuffer 对象。 Mesh 成员 Canvas_VBO 是一个 VertexBuffer 对象,因此不能在减速时实例化(我的意思是我不能在类字段)。例如,如果我想在 main.cpp 中创建对象,我可以这样做:

int main()
{
    std::array<float, 144> canvas_vertices = { ... };

    Buffers::VertexBuffer Canvas_VBO(canvas_vertices);
    // ^ buffer generated, 'canvas_vertices' inputted to buffer data, etc...
}

但是因为Canvas_VBO是类成员,我不能用这种方式实例化对象。

Mesh 构造函数中,我找到了一种解决方法,我创建了一个临时对象('aVBO'),然后将成员 Canvas_VBO 的内存地址设置为这个新的创建临时对象。这似乎工作正常,但我有一种琐碎的感觉,这可能不是一个好的做法,所以在这方面寻找一些建议,即这是不好的做法吗?还有其他解决方法吗?等等等等。

【问题讨论】:

  • 这是直接的未定义行为。构造函数结束后,aVBO 死亡,您的 Canvas_VBO 指针指向已删除的对象。 new/delete 可以提供帮助,但只需存储 std::unique_ptr&lt;Buffer::VertexBuffer&gt; 即可。
  • Canvas_VBO 必须是指针是否有特殊原因?我在您的代码中看不到任何理由为什么它不能像其他人一样成为普通成员......
  • @Max Langhof 不,我把它变成了一个指针,因为这样可以方便地从临时对象中传输内存地址,但是正如您所指出的,当临时对象时,内存将被释放超出范围,因此此方法无用。
  • 您可以将移动 ctor 和移动赋值运算符添加到 VertexBuffer,以便它可以有效地处理自身移动(如果甚至需要)。也许你应该展示一下VertexBuffer 的样子?
  • 使它成为普通成员(非指针)的问题是我看不到任何可以在对象上调用 VertexBuffer 构造函数的方法,看到好像 m_CanvasVertices 需要作为参数传递。

标签: c++ object opengl instantiation


【解决方案1】:

设置aVBO 的(堆栈)地址将不起作用,因为该对象在构造函数结束后被释放。

Canvas_VBO 设为std::unique_ptr&lt;Buffers::VertexBuffer&gt; 并在构造函数中使用std::make_unique&lt;Buffers::VertexBuffer&gt;(m_CanvasVertices) 动态分配它。

对于现代 C++ 内存管理读取智能指针。

【讨论】:

  • 仅供参考:使用单个反引号 (`) 格式化内联代码 sn-ps。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-10
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
  • 1970-01-01
  • 2015-11-24
相关资源
最近更新 更多