情况如下。我有共享库,其中包含类定义 -
QueueClass : IClassInterface
{
virtual void LOL() { do some magic}
}
我的共享库初始化类成员
QueueClass *globalMember = new QueueClass();
我的共享库导出 C 函数,它返回指向 globalMember 的指针 -
void * getGlobalMember(void) { return globalMember;}
我的应用程序像这样使用 globalMember
((IClassInterface*)getGlobalMember())->LOL();
现在非常棒的东西 - 如果我不从共享库引用 LOL,那么 LOL 就不会链接进来,从应用程序调用它会引发异常。原因 - VTABLE 包含 nul 代替指向 LOL() 函数的指针。
当我将 LOL() 定义从 .h 文件移动到 .cpp 时,它突然出现在 VTABLE 中并且一切正常。 什么解释了这种行为?! (gcc编译器+ARM架构_)
最佳答案
链接器是这里的罪魁祸首。当一个函数是内联的时,它有多个定义,一个在它被引用的每个 cpp 文件中。如果您的代码从不引用该函数,则它永远不会生成。
但是,vtable
布局是在编译时通过类定义确定的。编译器可以很容易地判断出 LOL()
是一个虚函数,并且需要在 vtable
中有一个条目。
当它到达应用程序的链接时间时,它会尝试填充 QueueClass::_VTABLE
的所有值,但找不到 LOL()
的定义> 并将其留空(空)。
解决方案是在共享库的文件中引用LOL()
。像 &QueueClass::LOL;
这样简单的东西。您可能需要将其分配给一次性变量,以使编译器停止提示无效的语句。
关于c++ - 为什么头文件中定义的 C++ 虚函数可能无法在 vtable 中编译和链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2898094/