虚拟覆盖和二进制兼容性

Virtual override and binary compatibility

本文关键字:兼容性 二进制 覆盖 虚拟      更新时间:2023-10-16

我有一个可以编译为共享库(或Windows中的DLL)的库。它有一个从另一个库中的另一个类派生的类。基类有一些虚方法,我的类覆盖了其中的一些。例如:

class Base {
public:
    virtual void method1();
    virtual void method2();
    virtual void method3();
};
class Derived: public Base {
public:
    virtual void method2();
};

现在我发现其中一个虚方法不太适合我的类。目前它没有重写这个方法,所以我想重写它来修复它的行为:

class Derived: public Base {
public:
    virtual void method2();
    virtual void method3();
};

这会破坏我的库与旧版本的二进制兼容性吗?

据我所知,这与仅仅添加虚函数不同,因为虚函数表中虚方法的数量和顺序保持不变。唯一的区别是,我的类的虚函数表中的一个特定条目现在将包含一个不同的值。这是正确的吗?

我也很确定目前使用我的库的应用程序都没有使用该方法,因为它完全被破坏了,从来没有工作过。所以我不担心会破坏对基方法实现的现有调用。我只是想确保我不会破坏任何东西

既然你在谈论dll,我假设这是Visual Studio/Windows中的c++。添加覆盖不会破坏二进制兼容性,因为虚函数表的大小不会改变。但是,如果不重新编译所有实例化派生的新实例的代码,可能会导致一些不期望的结果。这是因为虚函数表是由实例化源初始化的,而不是由实现派生类的源初始化的。

如果我理解正确,你在Dll1中有你的基类,在Dll2中有你的派生类。如果是这种情况,你所描述的变化不会影响Dll1。假设您将安装更新后的Dll2,那么每当您通过指针或对Base的引用访问Derived的实例时,应用程序将切换为调用Derived::method3()。

您的派生类(添加了新的虚方法)所在的库将不一定是与旧版本库兼容的二进制(ABI)库。这是因为当您添加被覆盖的虚方法时,您无法控制编译器如何生成虚表。