1. 什么是二進制兼容
所謂“二進制兼容性”指的就是在升級(也可能是 bug fix)庫文件的時候,不必重新編譯使用這個庫的可執(zhí)行文件或使用這個庫的其他庫文件,程序的功能不被破壞
2. 二進制不兼容會造成什么后果
如果庫A升級沒有能夠做到二進制兼容,那么所有依賴它的程序(或庫)都需要重新編譯,否則會出現(xiàn)各種未知異常,其直接現(xiàn)象就是程序莫名其妙地掛掉。
3. 哪些常見做法會破壞二進制兼容
(1) 給函數(shù)增加默認(rèn)參數(shù),現(xiàn)有的可執(zhí)行文件無法傳這個額外的參數(shù)
(2) 增加虛函數(shù),會造成 vtbl 里的排列變化。(不要考慮“只在末尾增加”這種取巧行為,因為你的 class 可能已被繼承。)
(3) 增加默認(rèn)模板類型參數(shù)
例如:template<typename T> class Grid{}變更為template<typename t, typenameContianer=vector> class Grid{}
(4) 改變 enum 的值,把 enum Color { Red = 3 }; 改為 Red = 4。這會造成錯位。當(dāng)然,由于 enum 自動排列取值,添加 enum 項也是不安全的,除非是在末尾添加
(5) 增加或減少類的數(shù)據(jù)成員
4. 哪些做法多半不會破壞二進制兼容
(1) 增加新的class
(2) 增加 non-virtual 成員函數(shù)
5. 反面教材:COM
在 C++ 中以虛函數(shù)作為接口基本上就跟二進制兼容性說拜拜了。具體地說,以只包含虛函數(shù)的 class (稱為 interface class)作為程序庫的接口,這樣的接口是僵硬的,一旦發(fā)布,無法修改。
比方說 M$ 的 COM,其 DirectX 和 MSXML 都以 COM 組件方式發(fā)布,我們來看看它的帶版本接口 (versioned interfaces):
IDirect3D7, IDirect3D8, IDirect3D9, ID3D10*, ID3D11*
IXMLDOMDocument, IXMLDOMDocument2, IXMLDOMDocument3
話句話說,每次發(fā)布新版本都引入新的 interface class,而不是在現(xiàn)有的 interface 上做擴充。這樣不能兼容現(xiàn)有的代碼,強迫客戶端代碼也要改寫。
回過頭來看看 C 語言,C/Posix
這些年逐漸加入了很多新函數(shù),同時,現(xiàn)有的代碼不用修改也能運行得很好。如果要用這些新函數(shù),直接用就行了,也基本不會修改已有的代碼。相反,COM
里邊要想用 IXMLDOMDocument3 的功能,就得把現(xiàn)有的代碼從 IXMLDOMDocument 全部升級到
IXMLDOMDocument3,很諷刺吧。
tip:如果遇到鼓吹在 C++ 里使用面向接口編程的人,可以拿二進制兼容性考考他。
6. 解決辦法
