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