c++ - 为什么头文件中定义的 C++ 虚函数可能无法在 vtable 中编译和链接?

标签 c++ interface virtual

情况如下。我有共享库,其中包含类定义 -

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/

相关文章:

c++ - 我没有得到目录中文件的实际数量。哪里有问题?

c++ - 正确删除指针双端队列

java - 处理类之间的对象

c# - 在C#中,接口(interface)可以被实例化吗?

c++ - 关于 C++ 中异常的虚函数

c++ - 使用 std::system 将 bash(例如 ssh)转换为 C++

c++ - 我如何从 HBITMAP 获取字节数组

java - 说接口(interface)也是一种类型是什么意思?

c++ - 不能将变量声明为类型,因为以下虚函数是抽象的

c++ - 我可以在构造函数中调用虚函数吗?