C++ 类vtable如何跨共享库工作?
假设我有一个名为C++ 类vtable如何跨共享库工作?,c++,vtable,virtual-functions,one-definition-rule,C++,Vtable,Virtual Functions,One Definition Rule,假设我有一个名为libplugin的共享库。在此共享库中,有一个类: class Plugin { public: virtual void doStuff(); }; 我们还假设有另一个名为libspecialplugin的共享库。它包含以下类和函数: class SpecialPlugin : public Plugin { public: virtual void doStuff(); }; Plugin *createSpecialPl
libplugin
的共享库。在此共享库中,有一个类:
class Plugin
{
public:
virtual void doStuff();
};
我们还假设有另一个名为libspecialplugin
的共享库。它包含以下类和函数:
class SpecialPlugin : public Plugin
{
public:
virtual void doStuff();
};
Plugin *createSpecialPlugin()
{
return new SpecialPlugin;
}
现在,假设我更改Plugin
并添加以下方法:
virtual void doMoreStuff();
我不重新编译libspecialplugin
当我这样做时会发生什么:
Plugin *plugin = createSpecialPlugin();
plugin->doMoreStuff();
我猜会发生以下情况之一:
Plugin::domorseuff()
方法libspecialplugin
库是否包含libplugin
可以用来确定哪些方法被重写的信息,即使在运行时也是如此?我对这里到底应该发生什么有点模糊。我必须添加一个巨大的免责声明:“与vtables有关的一切都是由实现定义的。”
如果插件构造函数和析构函数没有在头中内联声明,那么这将很好地工作。它必须是对libplugin.so库中的插件构造函数的实际函数调用。这意味着头部必须声明构造函数和析构函数,但不能定义它们,以避免生成编译器的自动版本
它看起来像:
class Plugin
{
public:
Plugin();
~Plugin();
virtual void doStuff();
};
还提供在类的末尾添加新的虚拟函数。如果它导致vtable中的任何其他函数移动,将破坏ABI
然后,当构建插件基类时,它将使用额外的函数创建新的vtable。然后SpecialPlugin将调整其一个虚拟功能并完成构建
其中一些可能取决于vtbl指针的特定编译器实现,但我已经看到了这一点。在任何使用这两个库的程序中,在两个不同的翻译单元中以不同的方式定义相同的类(
Plugin
),实际上违反了“一个定义规则”
标准规定(C++11 ISO 14882:2011,§3.2第5段):
一个类类型可以有多个定义(第9条)。。。
在程序中,只要每个定义以不同的形式出现
翻译单位,并提供满足以下要求的定义
要求。给定一个以上定义的名为D的实体
翻译单位,然后:
- D的每个定义应包含相同的令牌序列;及
Plugin
有两个不同的定义,一个在libplugin中烘焙,另一个在libspecialplugin中烘焙,因此它不符合标准
标准没有定义这一结果,因此任何事情都可能发生。没有“共享库”这样的东西,这是一个矛盾。您所说的是共享对象代码,它的工作原理与常规对象代码类似,只是始终与位置无关(如今,常规对象代码通常与位置无关,但并不总是必须如此)。