Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类vtable如何跨共享库工作?_C++_Vtable_Virtual Functions_One Definition Rule - Fatal编程技术网

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中烘焙,因此它不符合标准

    标准没有定义这一结果,因此任何事情都可能发生。

    没有“共享库”这样的东西,这是一个矛盾。您所说的是共享对象代码,它的工作原理与常规对象代码类似,只是始终与位置无关(如今,常规对象代码通常与位置无关,但并不总是必须如此)。