bit*_*ift 7 c++ final undefined-reference c++14
将final关键字添加到虚函数声明时,我遇到了一个奇怪的情况,其定义在一个单独的.cpp文件中.
请考虑以下示例:
IClass.hpp
class IClass //COM-like base interface
{
protected:
virtual ~IClass(){} //derived classes override this
public:
virtual void release() final;
};
Run Code Online (Sandbox Code Playgroud)
dllmain.cpp(共享库)
#include "IClass.hpp"
...
void IClass::release()
{
delete this;
}
...
Run Code Online (Sandbox Code Playgroud)
main.cpp(独立可执行文件)
//various includes here
...
int main(int argc, char** argv)
{
/* From "IGameEngine.hpp"
class IGameEngine : public IClass
{
...
};
*/
IGameEngine* engine = factoryGameEngine();
...
engine->release();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
事实上,GCC 4.9.2将报告undefined reference to 'IClass::release()'
我的目标是IClass::release()在将其实现隐藏在游戏引擎的共享库中时,将其作为不可覆盖的.
有什么建议?
对 GCC 的使用进行了一些挖掘final,结果发现标记为 Final 的虚拟函数得到了“去虚拟化”,这是一个优化步骤,旨在通过使用静态调度来加速虚拟调用,并可能内联它们。
这解释了链接器错误,因为它尝试链接IClass::release()到可执行文件,但无法在本地找到它。
这种“去虚拟化”行为也出现在 clang 上,但不太可能发生在 MSVC++ 上
部分相关建议
如果您需要一种通过指向抽象类(或抽象基类)的指针来释放对象的方法:
抽象基类需要一个纯虚析构函数 在类外部提供析构函数的默认定义(空范围) 像往常一样在所有派生类上实现析构函数
如果您还处理共享库:
从库中导出一对 Malloc/Free 函数 std::nothrow覆盖库头文件中的非数组 new/delete 运算符及其各自的版本从重写的运算符中调用上面的 Malloc/Free
由于接口实现将驻留在库内,因此请为您认为客户端可构造的每个接口导出一个工厂函数。
只需确保异常不会通过客户端和库之间的间隙传播。
这样,客户端应用程序就可以delete轻松地使用库的 CRT 分配的对象。