2011-07-19 58 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将被标记为弱符号,链接器将*随机*选择其中一个。如果您的代码依赖于可实例化的基类,该基类调用(对于该翻译单元不是纯粹的)虚拟函数,并且链接器已经选择了该函数纯净的虚表... –