从基类

时间:2015-07-14 18:50:07

标签: c++ opengl polymorphism glfw

所以,基本上我正在创建一个包装类来创建一个简单的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()函数使它工作正常。

1 个答案:

答案 0 :(得分:0)

当C ++初始化派生类(您的Teste类)时,它将首先构造基类(您的Application类)。 调用基类的构造函数时,派生类不可用。虚拟成员函数(execute)仍然是纯虚拟的,因此错误是纯虚函数调用。

构造函数不应该调用虚函数,因为它不会提供多态性。您可以提供Application的公共启动函数,并在构造函数外部调用它。

请参阅:Bjarne Stroustrup's C++ Style and Technique FAQ: Can I call a virtual function from a constructor?