为什么新的虚拟函数不会破坏二进制兼容性的现象?
why new virtual function will not break binary compatibility per phenomenon?
我正在学习基于这个 KDE wiki 的二进制兼容性,并看到
将虚函数添加到没有任何虚函数或虚基的类
会破坏兼容性。然后我试了一下。
假设我想创建一个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 %dn", m_len);
return m_len;
}
在第三个 exe 文件测试.exe中,使用了如下所示的快速字符串
// 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是在编译器周期内创建的,而不是在链接周期内创建的?
非虚拟函数FastString::length()
的调用与布局无关,DLL 中定义的函数知道实际的对象布局并找到正确的成员。您应该受到布局不兼容的影响,方法是公开m_len
并从 DLL 外部访问它。
虽然没有关于VMT位置的一般规则,但它通常由编译器创建并放入某个特定的翻译单元(*.obj)中,即定义第一个虚函数的地方。有时,当所有虚函数都是内联的时,必须应用更高级的策略,并且它们通常涉及链接器。但通常,当使用较旧的标头编译器时,将没有足够的提示涉及 VMT 的存在,并且不会为该对象创建 VMT 指针。
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 添加noexcept是否会破坏二进制兼容性
- 在Qt中使用C++Lambda函数作为插槽是否有助于保持库的二进制兼容性?
- 为什么新的虚拟函数不会破坏二进制兼容性的现象?
- 在类中添加新的成员变量会影响二进制兼容性
- 2015年视觉工作室的二进制兼容性
- 保证C++库二进制兼容性的简单方法,C链接
- 添加move构造函数会破坏二进制兼容性吗
- 关于 Linux 的二进制兼容性
- 我们什么时候打破二进制兼容性
- Linux二进制兼容性
- 可以添加静态变量破坏 Linux 上的二进制兼容性
- 使用按引用传递而不是按指针传递时的二进制兼容性
- 旧发行版上的二进制兼容性(使用C++11)
- 在C++中更改参数名称时的二进制兼容性
- 不同类中相同结构定义的二进制兼容性
- 内联如何限制升级版本的二进制兼容性
- VS2010和VS2012之间的二进制C++库兼容性
- 由于虚拟函数,二进制兼容性中断
- 更改方法以添加隐藏的this指针是否会破坏二进制兼容性