使用抽象函数时出现未处理的异常

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.

有两种解决方案:

  1. 您从 BasicShader 而不是 ShaderProgram 的构造函数调用 loadShaders()。这要求您将函数设置为受保护的而不是私有的。
  2. 您更改了 class 逻辑,并强制执行一个与构建过程不同的 load/initialisation 阶段。

如果我的假设是错误的并且你没有从构造函数中调用loadShaders(),请post你调用它的代码,以及它的初始化参数,我会更新答案。