从基类调用虚方法
Calling a virtual method from the base class
所以,基本上我正在创建一个包装器类,它创建一个简单的OpenGL应用程序。我的想法是,准备好后要有这样的东西:
#include "application.h"
#include "myClassDerivedFromApp.h"
int main()
{
myClassDerivedFromApp app(1024, 768, "My App Name", 3.3 /*OpenGL Version*/);
app.start();
return 0;
}
基本上这个类封装了一个简单的OpenGL窗口,使用GLFW。其思想是,当您想要创建一个新应用程序时,您只需从application类(我正在编写的)派生您的类。有了这个新类,你只需要重写虚拟方法(mainLoop、initialize和回调),你就会有一个工作的应用程序。
下面是基类:
#pragma once
// Std library
#include <string>
// OpenGL related
#include <GLglew.h>
#include <GLFWglfw3.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()函数使其正常工作。
当c++初始化一个派生类(您的Teste类)时,它将首先构造基类(您的Application类)。调用基类的构造函数时,派生类不可用。虚成员函数(execute)仍然是纯虚函数,因此错误是纯虚函数调用。
构造函数不应该调用虚函数,因为它不提供多态性。你可以为Application提供一个公共的start函数,并在构造函数之外调用它。
参见:Bjarne Stroustrup的c++风格和技术FAQ:我可以从构造函数调用虚函数吗?
- 如何强制从重写方法调用重写的方法基方法?
- C++:使用方法调用析构函数的顺序是什么?
- 派生类调用父类的方法,该方法调用重写的虚拟方法调用错误的方法
- 使用 object 中的方法调用带有 std::bind 和 std::function.target 的 C 样式函数
- 指向类方法调用的指针
- 如何使用 SFINAE 在方法调用中有条件地定义变量?
- 是否有可以处理方法调用依赖关系的设计模式?
- 如何缩短C++中的方法调用?
- 从部分专用模板方法调用模板非静态方法
- 有没有办法禁止派生类中的基类方法调用?
- 为什么这C++只在编译器上编码一个不明确的方法调用Microsoft?
- 从父方法调用子方法
- 如何将子方法调用到父方法
- 虚拟函数在哪里使用 vpointer to vtable 来解析方法调用,非虚拟方法存储在哪里以及如何解析它们?
- 从静态方法调用静态函数指针
- 从同一类中的另一个方法调用方法时出错
- 方法调用意外地像 l 值一样起作用
- 无法从派生的一个方法调用基类方法
- 从类方法调用命名空间中名为 Same 的函数时,重载解析失败
- C 多线程JAVA JNI方法调用