虚拟覆盖和二进制兼容性

时间:2011-09-08 16:34:45

标签: c++ override virtual binary-compatibility

我有一个可以编译为共享库(或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();
};

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

据我了解,它与仅添加虚函数不同,因为vtable中虚拟方法的数量和顺序保持不变。唯一的区别是我的类的vtable中的特定条目现在将包含不同的值。这是对的吗?

我也很确定当前使用我的库的应用程序都没有使用该方法,因为它完全被破坏而且永远无法运行。所以我不担心破坏对基本方法实现的现有调用。我只是想确保我不会破坏其他任何东西。

3 个答案:

答案 0 :(得分:3)

由于你在谈论DLL,我认为这是Visual Studio / Windows中的C ++。添加覆盖不会破坏二进制兼容性,因为vtable的大小不会改变。但是,如果不重新编译实例化Derived新实例的所有代码,则可能会导致一些不希望的结果。这是因为vtable是由实例化源初始化的,而不是实现Derived的类的源。

答案 1 :(得分:0)

如果我理解正确,你在Dll1中有你的Base类,在Dll2中有你的Derived类。如果是这种情况,您描述的更改不会影响Dll1。假设您将安装更新的Dll2,只要您通过指针或对Base的引用访问Derived实例,您的应用程序就会切换到调用Derived :: method3()。

答案 2 :(得分:0)

你的派生类(添加了新的虚方法)所在的库 not 必然是二进制(ABI)兼容旧版本的库。这是因为在添加重写的虚拟方法时,无法控制编译器如何生成vtable。