學習、工作中總結的條款,不喜勿擾~
由於標准委員會一直沒有統一標准的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的思想和做法有他的歷史局限性,不過也相當完備,但是,我不推崇。