C++二进制兼容性

来源:互联网 发布:淘宝上推广效果 编辑:程序博客网 时间:2024/06/05 05:04

学习、工作中总结的条款,不喜勿扰~

由于标准委员会一直没有统一标准的C++ ABI,导致各个厂商都有自己的一套体系,为了不出意外,循规蹈矩也有一定的必要,但可以斟酌,三思而后行。


能:
1. 可以添加非virtual函数
2. 可以添加enum到class
3. 可以追加enum值到已存在enum中
4. 可以去掉private限制符没有被inline函数调用或者被使用的且非virtual函数
5. 可以添加static数据成员
6. 添加新的class
7. 改变函数的默认参数
8. 改变class的friend修饰符


不能:
1. 对于已存在的class不能export or unexport
2. 改变class的继承关系
3. 改变模板参数
4. 改变fucntion的unexport、remove、inline、重载
5. 改变函数签名
6. 在不含有任何virtual成员的类添加virtual function
7. 改变virtual函数的顺序
8. 重载已存在的virtual function
9. 对于non-private的static成员或者non-static、non-member的public数据不能unexport、改变类型、改变CV-qualifiers



为了将来class的扩展
1. Pimpl
2. 添加non-inline virtual destructor
3. 是所有的contructors non-inline


C++ABI
1. 对象的内存布局
2. 虚函数的调用方式,通常是vptr/vtbl然后用vtbl[offset]调用
3. name mangling(名字重整)
4. RTTI和exception
5. 调用约定(参数传递的方式)


源码兼容但二进制不兼容
1. 给函数增加默认参数
2. 增加虚函数,会造纸vtbl的排列变化(只在末尾增加有问题,该class可能已被继承)
3. 增加默认模板参数类型,改变了name mangling
4. 改变已有enum的值
5. 增大class数据成员,造成sizeof变大


安全的做法
1. 增加class
2. 增加non-virtual成员函数
3. 修改数据成员名称,二进制代码是按偏移量访问
4. ...


解决方案
1. 静态链接
2. 动态库的版本管理来控制兼容性
3. PIMPL,头文件之暴露non-virtua;接口,并且class的大小固定

补充一点,COM的思想和做法有他的历史局限性,不过也相当完备,但是,我不推崇。

原创粉丝点击