gpt4 book ai didi

c++ - (2 个问题) 'class' 类型重定义(即使使用#pragma once),以及静态函数内部的静态成员对象初始化?

转载 作者:行者123 更新时间:2023-11-27 23:36:39 32 4
gpt4 key购买 nike

我一直在研究我的第一个 opengl、glfw 和 glm 项目(在 cmake 中),同时遵循在线教程,我想开始将我的代码组织到特定的类中以执行特定的任务(例如用于组织着色器的模型类和顶点);然而,一旦我组织了我的代码,我就遇到了两个问题。

首先,在我终于摆脱了代码中的所有语法错误之后,我遇到了两个单独的类(一个是静态类)的编译错误 'class' type redefinition 两次。我在唯一的头文件 (zachos.h) 的最顶部有 #pragma once,所以我不知道这里的问题是什么。为什么我的代码(见下文)会抛出这个错误?列出的确切错误消息是:

zachos.cpp(94): error C2011: 'zachos::Model': 'class' type redefinition
zachos.h(53): note: see declaration of 'zachos::Model'
zachos.cpp(173): error C2011: 'zachos::Mainframe': 'class' type redefinition
zachos.h(84): note: see declaration of 'zachos::Mainframe'

其次,我需要从该类的静态函数内部初始化一个静态成员对象。我使用 static Model mModel; 在我的头文件 (zachos.h) 中定义了对象,然后在我的代码文件 (zachos.cpp) 中重新定义了它,最后我在静态函数中创建了类使用复制操作符 Model model(gVertexBufferData, gColorBufferData); mModel = 模型;。我对这个工作有严重的怀疑(因为复制运算符只做浅拷贝),我不知道如何使用指针在函数内定义 mModel(我相信我必须使用 delete以某种方式)。这种形式的对象初始化是否有问题,有没有更好的方法?

代码(所有文件都在同一个目录下并被CMake引用,如果需要我也可以提供CMakeLists.txt文件):

zachos.h:

#pragma once

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <stdio.h>
#include <string.h>

#include <vector>

#include <sstream>
#include <iostream>
#include <fstream>

#include <cstdlib>
#include <ctime>

/*
Namespace that contains all basic codestuff for zachos.
*/
namespace zachos {
// Constant data

static const std::string DATA_DEF("#version 330 core\nlayout(location = 0) in vec3 vertexPosition_modelspace;\nlayout(location = 1) in vec3 vertexColor;\nout vec3 fragmentColor;\n\nuniform mat4 MVP;\n\nvoid main()\n{\n\tgl_Position = MVP * vec4(vertexPosition_modelspace, 1);\n\t\n\tfragmentColor = vertexColor;\n}\n\n#version 330 core\nin vec3 fragmentColor;\nout vec3 color;\n\nvoid main()\n{\n\tcolor = fragmentColor;\n}");
std::vector<GLfloat> gVertexBufferData = {
-1.0f, -1.0f, -1.0f, // triangle 1 : begin
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, // triangle 1 : end
1.0f, 1.0f, -1.0f, // triangle 2 : begin
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f, // triangle 2 : end
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
std::vector<GLfloat> gColorBufferData(12 * 3 * 3, 0);

/*
Enum of all possible error codes for the program to return on its own
*/
enum ErrorCodes {
SUCCESS,
GLFW_INIT_FAIL,
GLFW_WINDOW_CREATION_FAIL,
GLAD_INIT_FAIL,
WINDOW_FAIL
};

/*
Error callback function for glfw. Nothing special.
*/
void errorCallback(int error, const char* description);

/*
Load shaders function for convenience. Used especially by the Model class.
*/
GLuint loadShaders(std::string shaders);

/*
Class for creating models; it holds a VBO, CBO, and programID.
*/
class Model {
public:
std::vector<GLfloat> mVertexBufferData;
std::vector<GLfloat> mColorBufferData;

GLuint VBO;
GLuint CBO;

GLuint programID;

glm::mat4 model;

/*
Default Constructor. Must contain all vertex and color data from the get go.
*/
Model(std::vector<GLfloat> vertexBufferData, std::vector<GLfloat> colorBufferData);

/*
Model update() function, called every "tick"
*/
virtual void update();

/*
Model draw() function, called to draw the model
*/
virtual void draw();
};

/*
Wrapper class of the main window for handling events and perspective.
*/
class Mainframe {
public:
static GLFWwindow* window;

static glm::mat4 projection;
static glm::mat4 view;

static Model mModel;

static int i;

// Event functions

static void framebufferSizeCallback(GLFWwindow* window, int width, int height);
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);

/*
Class initialization function.
*/
static int init();

/*
Frame by frame drawing function.
*/
static int draw();

/*
Get whether the window should close or not
*/
static bool shouldClose();
};
}

zachos.cpp:

#include "zachos.h"

namespace zachos {

void errorCallback(int error, const char* description) {
fprintf(stderr, "GLFW error %d: %s\n", error, description);
}

GLuint loadShaders(std::string shaders) {

// Create the shaders
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

// Read the shader code
std::string shaderCode;
std::string vertexShaderCode;
std::string fragmentShaderCode;

//std::ifstream shaderStream(file_path, std::ios::in);
if (/*shaderStream.is_open()*/ true) {
//std::stringstream sstr;
//sstr << shaderStream.rdbuf();
//shaderCode = sstr.str();
shaderCode = shaders;
//shaderStream.close();

size_t val = shaderCode.find("#version", 8);
vertexShaderCode = shaderCode.substr(0, val);
fragmentShaderCode = shaderCode.substr(val);
}
else {
//printf("Impossible to open \"%s\". Are you in the right directory? Don't forget to read the FAQ!\n", file_path);
getchar();
return 0;
}

GLint result = GL_FALSE;
int infoLogLength;

// Compile Vertex Shader
char const * vertexSourcePointer = vertexShaderCode.c_str();
glShaderSource(vertexShaderID, 1, &vertexSourcePointer, nullptr);
glCompileShader(vertexShaderID);

// Check Vertex Shader
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &result);
glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
std::vector<char> vertexShaderErrorMessage(infoLogLength + 1);
glGetShaderInfoLog(vertexShaderID, infoLogLength, nullptr, &vertexShaderErrorMessage[0]);
printf("%s\n", &vertexShaderErrorMessage[0]);
}

// Compile Fragment Shader
char const * fragmentSourcePointer = fragmentShaderCode.c_str();
glShaderSource(fragmentShaderID, 1, &fragmentSourcePointer, nullptr);
glCompileShader(fragmentShaderID);

// Check Fragment Shader
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &result);
glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
std::vector<char> fragmentShaderErrorMessage(infoLogLength + 1);
glGetShaderInfoLog(fragmentShaderID, infoLogLength, nullptr, &fragmentShaderErrorMessage[0]);
printf("%s\n", &fragmentShaderErrorMessage[0]);
}

// Link the program
printf("Linking program\n");
GLuint programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);

// Check the program
glGetProgramiv(programID, GL_LINK_STATUS, &result);
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
std::vector<char> programErrorMessage(infoLogLength + 1);
glGetProgramInfoLog(programID, infoLogLength, nullptr, &programErrorMessage[0]);
printf("%s\n", &programErrorMessage[0]);
}

glDetachShader(programID, vertexShaderID);
glDetachShader(programID, fragmentShaderID);

glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);

return programID;
}

class Model {
public:

std::vector<GLfloat> mVertexBufferData;
std::vector<GLfloat> mColorBufferData;

GLuint VBO;
GLuint CBO;

GLuint programID;

glm::mat4 model = glm::mat4(1.0f);

Model(std::vector<GLfloat> vertexBufferData, std::vector<GLfloat> colorBufferData) {

mVertexBufferData = vertexBufferData;
mColorBufferData = colorBufferData;

// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &VBO);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(mVertexBufferData), &mVertexBufferData.front(), GL_STATIC_DRAW);

glGenBuffers(1, &CBO);
glBindBuffer(GL_ARRAY_BUFFER, CBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(mColorBufferData), &mColorBufferData.front(), GL_STATIC_DRAW);

// Create and compile our GLSL program from the shaders
GLuint programID = loadShaders(zachos::DATA_DEF);
glUseProgram(programID);
}

virtual void update() {
for (int v = 0; v < 12 * 3; v++) {
mColorBufferData[3 * v + 0] = (float)std::rand() / RAND_MAX;
mColorBufferData[3 * v + 1] = (float)std::rand() / RAND_MAX;
mColorBufferData[3 * v + 2] = (float)std::rand() / RAND_MAX;
}
glBufferData(GL_ARRAY_BUFFER, sizeof(mColorBufferData), &mColorBufferData.front(), GL_STATIC_DRAW);
}

virtual void draw() {
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, CBO);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);

// Setup some 3D stuff
glm::mat4 mvp = Mainframe::projection * Mainframe::view * model;

GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);

// Draw the array
glDrawArrays(GL_TRIANGLES, 0, mVertexBufferData.size() / 3);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
};

class Mainframe {
public:
static GLFWwindow* window;

static glm::mat4 projection;
static glm::mat4 view;

static Model mModel;

static int i;

static void framebufferSizeCallback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
glm::perspective(glm::radians(45.0f), (float)width / (float)height, 0.1f, 100.0f);
}

static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
switch (key) {
case GLFW_KEY_ESCAPE:

break;
}
}

static int init() {
// Initialize GLFW
int glfwInitRes = glfwInit();
if (!glfwInitRes) {
fprintf(stderr, "Unable to initialize GLFW\n");
return GLFW_INIT_FAIL;
}

// Set GLFW flags. Not exactly sure if these are needed.
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

// Attempt to create the main window.
window = glfwCreateWindow(1280, 720, "InitGL", nullptr, nullptr);
if (!window) {
fprintf(stderr, "Unable to create GLFW window\n");
glfwTerminate();
return GLFW_WINDOW_CREATION_FAIL;
}
glfwMakeContextCurrent(window);

// Initialize GLAD and OpenGL
int gladInitRes = gladLoadGL();
if (!gladInitRes) {
fprintf(stderr, "Unable to initialize glad\n");
glfwTerminate();
return GLAD_INIT_FAIL;
}

glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
glfwSetKeyCallback(window, keyCallback);

// Create da CUBANGLÉ
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);

for (int v = 0; v < 12 * 3; v++) {
gColorBufferData[3 * v + 0] = (float)std::rand() / RAND_MAX;
gColorBufferData[3 * v + 1] = (float)std::rand() / RAND_MAX;
gColorBufferData[3 * v + 2] = (float)std::rand() / RAND_MAX;
}
Model model(gVertexBufferData, gColorBufferData);
mModel = model;

// Set the clear color
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

projection = glm::perspective(glm::radians(45.0f), (float)1280 / (float)720, 0.1f, 100.0f);

view = glm::lookAt(
glm::vec3(4, 3, 3), // Camera is at (4,3,3), in World Space
glm::vec3(0, 0, 0), // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);

i = 60;

return SUCCESS;
}

static int draw() {

if (i <= 0) {
view = glm::lookAt(
glm::vec3(3 + 2 * (float)std::rand() / RAND_MAX, 3 + 2 * (float)std::rand() / RAND_MAX, 3 + 2 * (float)std::rand() / RAND_MAX), // Camera is at (), in World Space
glm::vec3(0, 0, 0), // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
mModel.update();

i = 60;
}
i--;

mModel.draw();

glfwSwapBuffers(window);
}

static bool shouldClose() {
return glfwWindowShouldClose(window);
}
};

}

主要.cpp:

#include "zachos.h"

/*
I'm pretty sure you know what this function is.
*/
int main(int argc, char* argv[]) {
// Seed the random number generator
std::srand(static_cast<unsigned int>(std::time(nullptr)));

// Implement Mainframe for shorthand
using zachos::Mainframe;
// set GLFW error callback function
glfwSetErrorCallback(zachos::errorCallback);

// Run the window initiazation function
int value = Mainframe::init();
if (!value) {
// Return if failed
return value;
}

// Main loop
while (!Mainframe::shouldClose()) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);

glfwPollEvents();

// Actually does the hard work
Mainframe::draw();
}

glfwTerminate();

return zachos::SUCCESS;
}

我还知道此代码中存在的其他可能问题。如果愿意,您也可以提及它们,但我的主要问题围绕这两个主要问题展开。

最佳答案

您似乎两次声明类“Model”和“Mainframe”,一次在 zachos.h 中,一次在 zachos.cpp 中。您应该在 header 中声明类

class Model {
public:
virtual void update();
...
}

然后在cpp中定义类

void Model::update() {
...
}

header 告诉编译器类的结构和内容,cpp 提供函数的实际作用。

关于你的第二点,我不确定你正在尝试实现什么,所以不知道是否有更好的方法。

关于c++ - (2 个问题) 'class' 类型重定义(即使使用#pragma once),以及静态函数内部的静态成员对象初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58715694/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com