2011-07-19 77 views

回答

3

是什麼意思維持二進制兼容性給你?

的對象佈局將是相同的,但你會被打破的一個定義規則除非重新編譯所有的代碼,在這一點二進制兼容性基本上是無用的。如果不重新編譯,那麼ODR就會被破壞,雖然它可能會起作用,但它也可能不起作用。

特別地,如果所有的類中的虛方法是純或內嵌定義,則編譯器可能會產生在每個翻譯單元,其包括報頭中的虛表並將其標記爲弱符號。然後鏈接器將選擇其中一個並丟棄所有其他的。在這種情況下,鏈接器不需要驗證所有的vtable是否完全相同,並且會隨機選擇一個(或以不確定的方式確定性地選擇一個),並且可以選擇一個這樣的vtable,其中該方法是純虛擬的,如果在基類的對象上調用該方法,最終可能會崩潰應用程序。

+0

在我的情況下,並非所有的虛擬方法都是純粹的,有混合。儘管如此,我想我會重建一切,而不是生活在不確定的環境中。 –

+0

具體來說,我有N個共享庫。我只通過第一個lib中的基類指針調用虛函數;其他N-1庫包含派生類,並重新實現該函數。我打算將pure更改爲非純文件,並僅重新編譯第一個庫。 –

4

不存在兼容性問題當你從純virtual切換到virtual然後重新編譯代碼。 (然而,virtualvirtual可能會導致問題。)

你應該照顧的唯一的事情是,非純virtual方法必須有一個機構。它們不能保持不被實現。即

class A { 
public: 
    virtual int foo() 
    { 
    return 0; //put some content 
    } 
}; 

你不能簡單地把像,

virtual int foo(); 

這將導致連接錯誤,即使你不使用它。

+0

這不是真正的安全,這是違反ODR(不同的翻譯單位對同一類型不同的定義),並可能導致在某些情況下的問題。 –

+0

@大衛,你能舉個例子嗎? – iammilind

+0

我想我在給出的答案中提供了,但我會盡量簡化。如果所有的虛擬方法都是純虛擬的或者在類定義中內聯定義的,那麼沒有一個創建vtable的翻譯單元,而是所有包含該頭的翻譯單元。 vtable將被標記爲弱符號,鏈接器將*隨機*選擇其中一個。如果您的代碼依賴於可實例化的基類,該基類調用(對於該翻譯單元不是純粹的)虛擬函數,並且鏈接器已經選擇了該函數純淨的虛表... –