Merging vertices into one vertice in OpenGL

I have a class where it crates a cube, load a shader, and render it, but i would like to know, how do I create two cubes, with two different vertices, two different matrices, and then merge these vertices together into one big mesh? So I can draw it once, but I dont want to configure the two cubes directly where I create the vertices, you know? I want to create both of vertices, and then merge them together based on their matrix positions.
Here is my class and the shader I use to render the cube:

PrimitiveCube.h


    #pragma once

    #include "Shader.h"
    #include <glad/include/glad/glad.h>
    #include <map>
    #include <string>
    #include <vector>

    using std::map;
    using std::vector;
    using std::string;

    class PrimitiveCube
    {
	vector<float> vertices;

	GLuint vbo_vertices, vbo_colors;
	GLuint ibo_cube_elements;

	Shader* shader;
	glm::mat4 transformation;

    public:
	PrimitiveCube(const glm::vec3& pos, const vector<float>& v);
	~PrimitiveCube();

	//here i pass the camera matrices to send to the cube's shader
	void Render(map<string, glm::mat4> matrices);
    };
    

PrimitiveCube.cpp



    #include "PrimitiveCube.h"

	PrimitiveCube::PrimitiveCube(const glm::vec3& pos, const vector<float>& v)
	{
		transformation = glm::translate(glm::mat4(1.0), pos);

		vertices = v;
		
		shader = new Shader("cube.vert", "cube.frag");

		GLfloat cube_vertices[] =
		{
			// front
			vertices[0], vertices[1], vertices[2],
			vertices[3], vertices[4], vertices[5],
			vertices[6], vertices[7], vertices[8],
			vertices[9], vertices[10], vertices[11],
			// back
			vertices[12], vertices[13], vertices[14],
			vertices[15], vertices[16], vertices[17],
			vertices[18], vertices[19], vertices[20],
			vertices[21], vertices[22], vertices[23],
		};

		//vertices 
		glGenBuffers(1, &vbo_vertices);
		glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
		glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW);

		GLfloat cube_colors[] = {
			// front colors
			0.6f, 1.0, 0.6f,
			0.6f, 1.0, 0.6f,
			0.6f, 1.0, 0.6f,
			0.6f, 1.0, 0.6f,
			// back colors
			0.6f, 1.0, 0.6f,
			0.6f, 1.0, 0.6f,
			0.6f, 1.0, 0.6f,
			0.6f, 1.0, 0.6f,
		};
		glGenBuffers(1, &vbo_colors);
		glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
		glBufferData(GL_ARRAY_BUFFER, sizeof(cube_colors), cube_colors, GL_STATIC_DRAW);

		GLushort cube_elements[] = {
			// front
			0, 1, 2,
			2, 3, 0,
			// top
			1, 5, 6,
			6, 2, 1,
			// back
			7, 6, 5,
			5, 4, 7,
			// bottom
			4, 0, 3,
			3, 7, 4,
			// left
			4, 5, 1,
			1, 0, 4,
			// right
			3, 2, 6,
			6, 7, 3,
		};
		glGenBuffers(1, &ibo_cube_elements);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_cube_elements);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW);
	}

	PrimitiveCube::~PrimitiveCube()
	{
		glDeleteBuffers(1, &vbo_vertices);
		glDeleteBuffers(1, &vbo_colors);
		glDeleteBuffers(1, &ibo_cube_elements);

		delete shader;
	}

	void PrimitiveCube::Render(map<string, glm::mat4> matrices)
	{
		shader->Use();

		//calculating the matrices i pass from where i call the render, with the names "projection" and "view"
		map<string, glm::mat4>::const_iterator& it = matrices.begin();
		while (it != matrices.end())
		{
			GLuint p = shader->GetUniformLocation(it->first);
			glUniformMatrix4fv(p, 1, GL_FALSE, glm::value_ptr(it->second));
			it++;
		}
		GLuint p = shader->GetUniformLocation("model");
		glUniformMatrix4fv(p, 1, GL_FALSE, glm::value_ptr(transformation));

		glEnableVertexAttribArray(glGetAttribLocation(shader->GetID(), "coord3d"));
		// Describe our vertices array to OpenGL (it can't guess its format automatically)
		glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
		glVertexAttribPointer(
			glGetAttribLocation(shader->GetID(), "coord3d"), // attribute
			3,                 // number of elements per vertex, here (x,y,z)
			GL_FLOAT,          // the type of each element
			GL_FALSE,          // take our values as-is
			0,                 // no extra data between each position
			0                  // offset of first element
		);

		glEnableVertexAttribArray(glGetAttribLocation(shader->GetID(), "v_color"));
		glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
		glVertexAttribPointer(
			glGetAttribLocation(shader->GetID(), "v_color"), // attribute
			3,                 // number of elements per vertex, here (R,G,B)
			GL_FLOAT,          // the type of each element
			GL_FALSE,          // take our values as-is
			0,                 // no extra data between each position
			0                  // offset of first element
		);

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_cube_elements);
		int size;
		glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
		glDrawElements(GL_TRIANGLES, size / sizeof(GLushort), GL_UNSIGNED_SHORT, 0);

		glDisableVertexAttribArray(glGetAttribLocation(shader->GetID(), "coord3d"));
		glDisableVertexAttribArray(glGetAttribLocation(shader->GetID(), "v_color"));

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 	// Unbind the VBO
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		shader->Unuse();
	}

cube.vert



    #version 330

	attribute vec3 coord3d;
	attribute vec3 v_color;

	uniform mat4 model;
	uniform mat4 projection;
	uniform mat4 view;

	varying vec3 f_color;

	void main(void) 
	{
	  gl_Position = projection * view * model * vec4(coord3d, 1.0);
	  f_color = v_color;
	}

cube.frag


    #version 330

	varying vec3 f_color;

	void main(void) 
	{
	  gl_FragColor = vec4(f_color.x, f_color.y, f_color.z, 1.0);
	}

Oh and btw, I use SDL+ OpenGL, GLAD and GLM.