使用抽象函数时出现未处理的异常
Unhandled Exception when using abstract function
我试图在我的程序中使用加载基本着色器,但加载后,我得到一个未处理的异常弹出框。我创建了一个基础 class 来完成加载通用着色器的所有常见部分。在基础 class 中,我有一个受保护的虚函数和 public 函数来处理 OpenGL 属性。这是正在发生的事情的两个基本示例:
class ShaderProgram // Base class
{
public:
...
protected:
void bindAttribute(GLuint attribNumber, const char* variableName);
virtual void bindAttributes() = 0; // needed for different shaders
private:
GLuint programID;
void loadShaders(const char* vertFile, const char* fragFile);
}
class BasicShader : public ShaderProgram // derived class
{
public:
...
protected:
void bindAttributes() { bindAttribute(0, "position"); }
...
}
现在 loadShaders()
:
programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
bindAttributes(); // Unhandled Exception pointing here
当我尝试 运行 时出现此错误。但是,如果我将 bindAttributes()
替换为 bindAttribute()
中调用的 glBindAttribLocation(programID, 0, "position")
,则程序 运行s 应该正常运行。关于导致此错误的原因有什么想法吗?
我看到 loadShaders()
对 ShaderProgram
是私有的。根据您描述的症状和解决方法,我怀疑您是从 class 的构造函数中调用它的。
如果是这种情况,是因为在构造过程中使用了纯虚函数。更具体地说,从基础ShaderProgram
派生的classBasicShader
的构造过程是这样的:
- 首先构建 class
ShaderProgram
的基础对象。此时对象只有一个ShaderProgramm
。虚拟的
您可以在其构造函数中调用的函数仍然是在基 class 中定义的函数。
- 然后在基础对象之上构造派生对象。只有当你进入派生对象的构造函数时,
BasicShader
的虚函数将生效。
所以如果你从ShaderProgramm
的构造函数中调用loadShaders()
,它最终会尝试调用bindAttributes()
,它仍然是一个纯虚函数(即未定义).
Standard 10.4/6: Member functions can be called from a constructor
(or destructor) of an abstract class; the effect of making a virtual
call to a pure virtual function directly or indirectly for the object
being created (or destroyed) from such a constructor (or destructor)
is undefined.
有两种解决方案:
- 您从
BasicShader
而不是 ShaderProgram
的构造函数调用 loadShaders()
。这要求您将函数设置为受保护的而不是私有的。
- 您更改了 class 逻辑,并强制执行一个与构建过程不同的 load/initialisation 阶段。
如果我的假设是错误的并且你没有从构造函数中调用loadShaders()
,请post你调用它的代码,以及它的初始化参数,我会更新答案。
我试图在我的程序中使用加载基本着色器,但加载后,我得到一个未处理的异常弹出框。我创建了一个基础 class 来完成加载通用着色器的所有常见部分。在基础 class 中,我有一个受保护的虚函数和 public 函数来处理 OpenGL 属性。这是正在发生的事情的两个基本示例:
class ShaderProgram // Base class
{
public:
...
protected:
void bindAttribute(GLuint attribNumber, const char* variableName);
virtual void bindAttributes() = 0; // needed for different shaders
private:
GLuint programID;
void loadShaders(const char* vertFile, const char* fragFile);
}
class BasicShader : public ShaderProgram // derived class
{
public:
...
protected:
void bindAttributes() { bindAttribute(0, "position"); }
...
}
现在 loadShaders()
:
programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
bindAttributes(); // Unhandled Exception pointing here
当我尝试 运行 时出现此错误。但是,如果我将 bindAttributes()
替换为 bindAttribute()
中调用的 glBindAttribLocation(programID, 0, "position")
,则程序 运行s 应该正常运行。关于导致此错误的原因有什么想法吗?
我看到 loadShaders()
对 ShaderProgram
是私有的。根据您描述的症状和解决方法,我怀疑您是从 class 的构造函数中调用它的。
如果是这种情况,是因为在构造过程中使用了纯虚函数。更具体地说,从基础ShaderProgram
派生的classBasicShader
的构造过程是这样的:
- 首先构建 class
ShaderProgram
的基础对象。此时对象只有一个ShaderProgramm
。虚拟的 您可以在其构造函数中调用的函数仍然是在基 class 中定义的函数。 - 然后在基础对象之上构造派生对象。只有当你进入派生对象的构造函数时,
BasicShader
的虚函数将生效。
所以如果你从ShaderProgramm
的构造函数中调用loadShaders()
,它最终会尝试调用bindAttributes()
,它仍然是一个纯虚函数(即未定义).
Standard 10.4/6: Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.
有两种解决方案:
- 您从
BasicShader
而不是ShaderProgram
的构造函数调用loadShaders()
。这要求您将函数设置为受保护的而不是私有的。 - 您更改了 class 逻辑,并强制执行一个与构建过程不同的 load/initialisation 阶段。
如果我的假设是错误的并且你没有从构造函数中调用loadShaders()
,请post你调用它的代码,以及它的初始化参数,我会更新答案。