为什么新的虚函数不会破坏每个现象的二进制兼容性?

时间:2018-03-16 09:24:46

标签: c++ binary-compatibility

我正在学习基于此KDE wiki的二进制兼容性,并看到

  

add a virtual function到没有任何虚拟功能或虚拟基地的课程

将破坏兼容性。然后我试了一下。

假设我想创建一个 FastString.dll 来提供,这里是定义。

//FastString.h

#ifdef _DLL_EXPORT
#define LIB_EXPORT __declspec(dllexport)
#else
#define LIB_EXPORT __declspec(dllimport)
#endif

class LIB_EXPORT FastString
{
public:
    FastString(void);
    ~FastString(void);

    int length();

private:
    int m_len;
    unsigned char *m_bytes;
};

和实施

//FastString.cpp
#include "FastString.h"

FastString::FastString(void)
{
    m_len = 0;
}

FastString::~FastString(void)
{
}

int FastString::length()
{
    printf("Function of length, string len is %d\n", m_len);
    return m_len;
}

在第三个exe文件 test.exe 中,使用如下的FastString

// main.cpp

#include <conio.h>
#include "FastString.h"

int _tmain(int argc, _TCHAR* argv[])
{
    FastString str;
    str.length();

    printf("Please input any key to exit...");
    _getch();
    return 0;
}

请注意:main.cpp中包含的FastString.h是另一个文件,当我在FastString中添加虚拟函数时,修改在FastString.dll下。

它们位于相同的解决方案(编译器:VS2012)中,并且构建成功。之后,我在FastString.h中添加了一个新的虚函数。

virtual bool isEmpty();

在FastString.cpp中,我用简单的返回

实现它
bool FastString::isEmpty()
{
    return false;
}

然后我单独构建FastString.dll,然后重新运行test.exe。输出与前一个输出相同,没有任何错误 那么,为什么这种行为不会打破二进制兼容性呢?
根据我的理解,实例str应该有一个 vtable 指针,并且内存布局必须已经更改。
我还有一个基于VS工具的调试,发现str仍然没有 _vptr ,这是否意味着 vtable 是在编译器下创建的期间,而不是链接期间?

1 个答案:

答案 0 :(得分:0)

调用非虚函数FastString::length()是独立于布局的,并且在DLL中定义的函数知道实际的对象布局并找到正确的成员。通过使m_len公开并从DLL外部访问它,您应该遇到布局不兼容问题。

虽然没有关于VMT所在位置的一般规则,但它通常由编译器创建并放入某个特定的转换单元(* .obj)内,即定义第一个虚拟函数的位置。有时,例如,当所有虚函数都是内联时,必须应用更高级的策略,并且它们通常涉及链接器。但通常在使用较旧的头文件编译器时,没有足够的提示涉及VMT的存在,并且不会为该对象创建VMT指针。