Resolve build errors due to circular dependency amongst classes
(11个答案)
在11个月前关闭。
我要自学C++ OpenGL,VisualStudio说我的代码还可以。但是,如果我编译代码,则会遇到许多语法错误。我真的不明白。
这是错误消息:
1>------ Erstellen gestartet: Projekt: OpenGL, Konfiguration: Release Win32 ------
1>Application.cpp
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Engine.h(50,25): error C2061: Syntaxfehler: Bezeichner "Renderer"
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Application.cpp(35,33): error C2660: "Engine::gameLoop": Funktion akzeptiert keine 3 Argumente
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Engine.h(50,7): message : Siehe Deklaration von "Engine::gameLoop"
1>Buffers.cpp
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Renderer.h(13,26): error C3646: "parseShader": Unbekannter Überschreibungsspezifizierer
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Renderer.h(13,26): error C2059: Syntaxfehler: "("
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Renderer.h(13,54): error C2238: Unerwartete(s) Token vor ";"
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Renderer.h(22,39): error C2061: Syntaxfehler: Bezeichner "GameVars"
1>Engine.cpp
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Renderer.h(13,26): error C3646: "parseShader": Unbekannter Überschreibungsspezifizierer
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Renderer.h(13,26): error C2059: Syntaxfehler: "("
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Renderer.h(13,54): error C2238: Unerwartete(s) Token vor ";"
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Renderer.h(22,39): error C2061: Syntaxfehler: Bezeichner "GameVars"
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Engine.cpp(72,12): error C2660: "Renderer::render": Funktion akzeptiert keine 2 Argumente
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Renderer.h(22,7): message : Siehe Deklaration von "Renderer::render"
1>Renderer.cpp
1>C:\Users\schko\source\repos\OpenGL\OpenGL\src\Engine.h(50,25): error C2061: Syntaxfehler: Bezeichner "Renderer"
1>Die Erstellung des Projekts "OpenGL.vcxproj" ist abgeschlossen -- FEHLER.
========== Erstellen: 0 erfolgreich, 1 fehlerhaft, 0 aktuell, 0 übersprungen ==========
这是我的代码...
Application.cpp:
#include "Buffers.h"
#include "Renderer.h"
#include "Engine.h"
int main()
{
float vertices[] =
{
-0.5f, -0.5f, // 0
0.5f, -0.5f, // 1
0.5f, 0.5f, // 2
-0.5f, 0.5f // 3
};
unsigned int indices[] =
{
0, 1, 2,
2, 3, 0
};
Buffers buff(vertices, indices, 4 * 2, 6);
Renderer r;
Engine engine;
if (engine.err != 0)
return -1;
float g = 0.0f;
float b = 1.0f;
float iG = 0.05f;
float iB = -0.05f;
GameVars vars = { 0.0f, g, b, 1.0f };
engine.gameLoop(r, buff, engine);
while (!engine.terminated)
{
if (g > 1.0f)
iG = -0.005f;
else if (g < 0.0f)
iG = 0.005f;
if (b > 1.0f)
iB = -0.005f;
else if (b < 0.0f)
iB = 0.005f;
g += iG;
b += iB;
engine.setVars({ 0.0f, g, b, 1.0f });
}
buff.~Buffers();
r.~Renderer();
engine.~Engine();
return 0;
}
Engine.cpp:
#include "Engine.h"
void GLClearError()
{
while (glGetError() != GL_NO_ERROR);
}
bool GLLogCall(const char* function, const char* file, int line)
{
while (GLenum error = glGetError())
{
std::cout << "[OpenGL Error] (" << error << ") at " << function << " in " << file << " on line " << line << std::endl;
return false;
}
return true;
}
Engine::Engine()
{
err = init();
terminated = false;
std::cout << glGetString(GL_VERSION) << std::endl;
}
Engine::~Engine()
{
glfwTerminate();
}
int Engine::init()
{
if (!glfwInit())
{
std::cout << "Init of GLFW failed!" << std::endl;
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(1020, 760, "MyLearningApplication", NULL, NULL);
if (!window)
{
std::cout << "Creating the Window failed!" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
if (glewInit() != GLEW_OK)
{
std::cout << "Init of GLEW failed!" << std::endl;
return -1;
}
return 0;
}
void Engine::gameLoop(Renderer renderer, Buffers buffer, Engine This)
{
std::thread thread([](Renderer renderer, Buffers buffer, Engine eng) {
while (!glfwWindowShouldClose(eng.getWindow()))
{
GLCall(glClear(GL_COLOR_BUFFER_BIT));
renderer.render(buffer, eng.getVars());
glfwSwapBuffers(eng.getWindow());
glfwPollEvents();
}
eng.terminated = true;
}, renderer, buffer, This);
}
Engine.h:
#pragma once
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Buffers.h"
#include "Renderer.h"
#include <iostream>
#include <string>
#include <thread>
#define ASSERT(x) if (!(x)) __debugbreak();
#define GLCall(x)\
GLClearError();\
x;\
ASSERT(GLLogCall(#x, __FILE__, __LINE__));
void GLClearError();
bool GLLogCall(const char* function, const char* file, int line);
struct ShaderSource
{
std::string VertexSource;
std::string FragmentSource;
};
struct GameVars
{
float r;
float g;
float b;
float alpha;
};
class Engine
{
private:
GLFWwindow* window;
GameVars vars;
int init();
public:
int err;
bool terminated;
Engine();
~Engine();
void gameLoop(Renderer renderer, Buffers buffer, Engine This);
inline GLFWwindow* getWindow() const { return window; }
inline GameVars getVars() const { return vars; }
inline void setVars(GameVars newVars) { vars = newVars; }
};
Renderer.cpp:
#include "Renderer.h"
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
Renderer::Renderer()
{
ShaderSource source = parseShader("res/shaders/basic.shader");
m_Shader1 = createShader(source.VertexSource, source.FragmentSource);
GLCall(glUseProgram(m_Shader1));
GLCall(m_uVar1 = glGetUniformLocation(m_Shader1, "u_Color"));
GLCall(glUseProgram(0));
}
Renderer::~Renderer()
{
GLCall(glDeleteProgram(m_Shader1));
}
ShaderSource Renderer::parseShader(const std::string filePath)
{
std::ifstream stream(filePath);
enum class ShaderType
{
NONE = -1, VERTEX = 0, FRAGMENT = 1
};
std::string line;
std::stringstream ss[2];
ShaderType type = ShaderType::NONE;
while (getline(stream, line))
{
if (line.find("#shader") != std::string::npos)
{
if (line.find("vertex") != std::string::npos)
type = ShaderType::VERTEX;
else if (line.find("fragment") != std::string::npos)
type = ShaderType::FRAGMENT;
}
else
{
ss[(int)type] << line << "\n";
}
}
return { ss[0].str(), ss[1].str() };
}
unsigned int Renderer::compileShader(unsigned int type, std::string source)
{
GLCall(unsigned int id = glCreateShader(type));
const char* src = source.c_str();
GLCall(glShaderSource(id, 1, &src, nullptr));
GLCall(glCompileShader(id));
int result;
GLCall(glGetShaderiv(id, GL_COMPILE_STATUS, &result));
if (result == GL_FALSE)
{
int length;
GLCall(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
char* msg = (char*)alloca(length * sizeof(char));
GLCall(glGetShaderInfoLog(id, length, &length, msg));
std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << "shader!" << std::endl;
std::cout << msg << std::endl;
return 0;
}
return id;
}
unsigned int Renderer::createShader(std::string vertexShader, std::string fragmentShader)
{
GLCall(unsigned int program = glCreateProgram());
unsigned int vs = compileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = compileShader(GL_FRAGMENT_SHADER, fragmentShader);
GLCall(glAttachShader(program, vs));
GLCall(glAttachShader(program, fs));
GLCall(glLinkProgram(program));
GLCall(glValidateProgram(program));
GLCall(glDeleteShader(vs));
GLCall(glDeleteShader(fs));
return program;
}
Buffers Renderer::createBuffer(const void* vertices, const unsigned int* indices, unsigned int vertexCount, unsigned int indexCount)
{
Buffers newB(vertices, indices, vertexCount, indexCount);
return newB;
}
void Renderer::render(Buffers buffer, GameVars vars)
{
buffer.bind();
GLCall(glUseProgram(m_Shader1));
GLCall(glUniform4f(m_uVar1, vars.r, vars.g, vars.b, vars.alpha));
GLCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr));
GLCall(glUseProgram(0));
buffer.unbind();
}
Renderer.h:
#pragma once
#include "Engine.h"
#include "Buffers.h"
class Renderer
{
private:
unsigned int m_Shader1;
unsigned int m_uVar1;
ShaderSource parseShader(const std::string filePath);
unsigned int compileShader(unsigned int type, std::string source);
unsigned int createShader(std::string vertexShader, std::string fragmentShader);
public:
Renderer();
~Renderer();
Buffers createBuffer(const void* vertices, const unsigned int* indices, unsigned int vertexCount, unsigned int indexCount);
void render(Buffers buffer, GameVars vars);
};
Buffers.cpp:
#include "Buffers.h"
#include "Engine.h"
Buffers::Buffers(const void* vertices, const unsigned int* indices, unsigned int vertexCount, unsigned int indexCount)
: m_iCount(indexCount)
{
ASSERT(sizeof(unsigned int) == sizeof(GLuint));
GLCall(glGenVertexArrays(1, &m_vaoID));
GLCall(glBindVertexArray(m_vaoID));
GLCall(glGenBuffers(1, &m_vBuffID));
GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_vBuffID));
GLCall(glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(float), vertices, GL_STATIC_DRAW));
GLCall(glEnableVertexAttribArray(0));
GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0));
GLCall(glGenBuffers(1, &m_iBuffID));
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_iBuffID));
GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(GLuint), indices, GL_STATIC_DRAW));
GLCall(glBindBuffer(GL_ARRAY_BUFFER, 0));
}
Buffers::~Buffers()
{
GLCall(glDeleteBuffers(1, &m_iBuffID));
GLCall(glDeleteBuffers(1, &m_vBuffID));
GLCall(glDeleteVertexArrays(1, &m_vaoID));
}
void Buffers::bind() const
{
GLCall(glBindVertexArray(m_vaoID));
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_iBuffID));
}
void Buffers::unbind() const
{
GLCall(glBindVertexArray(0));
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
Buffers.h:
#pragma once
class Buffers
{
private:
unsigned int m_iBuffID;
unsigned int m_vBuffID;
unsigned int m_vaoID;
unsigned int m_iCount;
public:
Buffers(const void* vertices, const unsigned int* indices, unsigned int vertexCount, unsigned int indexCount);
~Buffers();
void bind() const;
void unbind() const;
inline unsigned int getIndexCount() { return m_iCount; }
};
着色器工作正常。
我是一名优秀的程序员,十分优秀!