构造函数C++中的虚拟方法

Virtual method in constructor C++

本文关键字:虚拟 方法 C++ 构造函数      更新时间:2023-10-16

我有一个类Shader,在它的构造函数中,有编译着色器,绑定属性然后链接着色器程序的语句。问题是我希望子类具有不同的属性,但这必须在链接之前发生。虚拟方法在这里不起作用。我该怎么办?

Shader::Shader(const char* v, const char* f) {
    program = glCreateProgram();
    const char* vsrc = nullptr;
    const char* fsrc = nullptr;
    tls::readTextFile(std::ifstream(v, std::ios::binary), vsrc);
    tls::readTextFile(std::ifstream(f, std::ios::binary), fsrc);
    m_vertShader = compile(vsrc, GL_VERTEX_SHADER);
    m_fragShader = compile(fsrc, GL_FRAGMENT_SHADER);
    glAttachShader(program, m_vertShader);
    glAttachShader(program, m_fragShader);
    bindAttribs(); // it must happen before linking, in child class too.
    glLinkProgram(program);
    getUniforms();
    setUniforms();
}

和儿童班:

void BasicShader::bindAttribs() {
    bindAttribute(0, "pos");
    bindAttribute(2, "vt");
} // this method is not called

问题是您的构造函数是整体式的。将其拆分为一个"预烘焙"受保护的构造函数和一个执行链接(也受保护)的"最终构造"帮助程序函数。这样,您可以自定义在施工期间但在链接之前发生的情况。

更通用的方法是工厂函数。

据我所知,这里有两个选项:

1. 将属性作为参数传递给构造函数

Shader::Shader(const char* v, const char* f,
    const std::vector<std::pair<int, std::string>> &attrs)
    /* Or some simpler type with the same functionality */
{
    ...
    for (auto &&attr : attrs)
        bindAttr(attr.first, attr.second);
    ...
}

2. 将所有初始化从构造函数移动到单独的方法

bool Shader::initialize(const char* v, const char* f)
{
    // Here you actually can use virtual methods, yay!
    // ...and even report errors via return value (unless you were planning to use exceptions)
    return true;
}