如果使用非公共类,则vtable是否在二进制文件之间持久存在?

说我有三个库,都是用C ++编写的:

  1. logging.a:一个用于记录日志的静态库。它定义了一个抽象类,其他类可使用该抽象类来自定义其日志记录(通过实现纯虚拟方法virtual void CustomLogger::customLogging(std::string) = 0)。
  2. libmainproject.so:主库。它包含一个外部未知的类(CustomLoggerImpl),该类扩展了CustomLogger并实现了自定义日志记录方法。
  3. libplugin.so:一个插件库,需要记录内容并希望将其记录与libmainproject中的记录集成。

libmainprojectlibplugin之间的接口是C接口,尽管两个库的内部都是用C ++编写的。

libplugin不知道CustomLoggerImpl内是否存在libmainproject,但确实从CustomLogger知道了接口logging

为了使用来自libplugin的自定义日志记录,我已将指向CustomLoggerImpl的指针传递为void *(因为它是通过C接口发生的,因此无法使用自定义对象)。

一旦我需要登录插件,就将void *(指向CustomLoggerImpl对象)转换为CustomLogger *(Liskov替换原理)。然后,我调用customLogger->customLogging("whatever");

尽管没有崩溃,但呼叫似乎并未打到libmainproject。为什么会这样?我认为问题是vtable出现了问题,因此它无法从其他没有对象定义的二进制文件中正常工作,但还需要更多深入解释为什么会发生这种情况。

zyc007 回答:如果使用非公共类,则vtable是否在二进制文件之间持久存在?

动态链接(共享)库不是由Standard C ++定义的,因此您处于特定于实现的行为中。

执行通常会做合理的事情;合理地假设CustomLogger在所有二进制文件中具有相同的vtable布局。标准甚至没有规定vtable,因此这不是一个硬性声明。

支持动态链接库的实现通常不假定所有代码都驻留在单个二进制文件中。在Windows上,MSVC的假设要少一些,因为它具有一个__declspec(dllimport)扩展名,可以专门告诉编译器某些代码来自另一个二进制文件。但是您的问题明确表明您没有使用MSVC。您的编译器不会仅仅因为customLogging会调用libplugin.so而假设libplugin.so中必须定义customLogging覆盖。

因此,我要同意VTT。这里最大的问题似乎是您正在通过CustomLoggerImpl*CustomLogger*投射到void* CustomLoggerImpl* -> CustomLogger* -> void* -> CustomLogger*。转换为基类应该在C ++代码中显式进行。

本文链接:https://www.f2er.com/3124183.html

大家都在问