所以,基本上我正在创建一个包装类来创建一个简单的OpenGL应用程序。我的想法是在准备好的时候有这样的事情:
#include "application.h"
#include "myClassDerivedFromApp.h"
int main()
{
myClassDerivedFromApp app(1024, 768, "My App Name", 3.3 /*OpenGL Version*/);
app.start();
return 0;
}
所以,基本上这个类使用GLFW封装了一个简单的OpenGL窗口。我们的想法是,当您想要创建一个新的应用程序时,您只需从Application类派生您的类(我正在编写)。使用这个新类,您只需覆盖虚拟方法(mainLoop,initialize和callbacks),您将拥有一个有效的应用程序。
这是基类:
#pragma once
// Std library
#include <string>
// OpenGL related
#include <GL\glew.h>
#include <GLFW\glfw3.h>
// lh namespace
#include "camera.h"
#include "window.h"
namespace lh
{
//!
//! Class definition of a generic OpenGL Application. Receives the window size,
//! the Application's name and OpenGL's version used.
//!
class Application
{
public:
Application(int windowWidth, int windowHeight, std::string name, float versionOpenGL);
virtual ~Application();
void start();
protected:
virtual void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mode) = 0;
virtual void mouseCallback(GLFWwindow* window, double xpos, double ypos) = 0;
virtual void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) = 0;
virtual void mainLoop() = 0;
virtual void initialize() = 0;
private:
void execute();
// Callbacks
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mode);
static void MouseCallback(GLFWwindow* window, double xpos, double ypos);
static void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
// Attributes
GLFWwindow* window_;
int width_;
int height_;
std::string name_;
int versionMajor_;
int versionMinor_;
};
}
所以我所做的是将所有在派生类中创建所需的函数(位于protected
中)声明为纯虚函数。以下是实施:
void lh::Application::start()
{
initialize();
execute();
}
void lh::Application::execute()
{
while (glfwWindowShouldClose(window_)) {
glfwPollEvents();
mainLoop();
glfwSwapBuffers(window_);
}
}
基本上方法start
调用虚方法initialize
和方法execute,调用方法mainLoop
。这样,如果我想创建新的东西,我不必每次都设置glfw和窗口,我只是从这个类派生并实现纯虚方法。
这是一个想法,但是Visual Studio报告了一个我称之为纯虚函数的错误,这可能意味着我无法做我目前正在做的事情。但我没有看到另一种方法(确保Application类保持抽象)。
我没有包含所有的实现(构造函数和回调),因为我认为它们与当前问题无关(构造函数工作正常)。
以下是我测试此课程的方法:
#pragma once
#include "application.h"
class Teste :
public lh::Application
{
public:
Teste(int width, int height, std::string name, float versionOpenGL);
~Teste();
protected:
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mode);
void mouseCallback(GLFWwindow* window, double xpos, double ypos);
void scrollCallback(GLFWwindow* window, double xoffset, double yoffset);
void mainLoop();
void initialize();
};
实施:
#include "teste.h"
#include <iostream>
Teste::Teste(int width, int height, std::string name, float versionOpenGL)
: Application(width, height, name, versionOpenGL)
{
}
Teste::~Teste()
{
}
void Teste::initialize()
{
std::cout << "INTIALIZE" << std::endl;
}
void Teste::mainLoop()
{
std::cout << "AAAAAAAA" << std::endl;
}
void Teste::keyCallback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
}
void Teste::mouseCallback(GLFWwindow* window, double xpos, double ypos)
{
}
void Teste::scrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
}
上面的代码工作正常。问题是在构造函数中我最后调用了start()
,它正在调用虚方法。从构造函数中删除它并将其传递给main()函数使它工作正常。
答案 0 :(得分:0)
当C ++初始化派生类(您的Teste类)时,它将首先构造基类(您的Application类)。 调用基类的构造函数时,派生类不可用。虚拟成员函数(execute)仍然是纯虚拟的,因此错误是纯虚函数调用。
构造函数不应该调用虚函数,因为它不会提供多态性。您可以提供Application的公共启动函数,并在构造函数外部调用它。
请参阅:Bjarne Stroustrup's C++ Style and Technique FAQ: Can I call a virtual function from a constructor?