struct Gadget { // some content }; struct Widget { virtual Gadget* getGadget(); };
任何调用getGadget()的代码都必须在接收Gadget *时工作,但是当它接收到指向从Gadget派生的类型的指针时,相同的代码(实际上是相同的编译二进制代码)必须工作(可能是一个定义的在一个完全不同的图书馆).我可以合理地看到这种情况发生的唯一方法是所有非联合类类型T和U的sizeof(T *)== sizeof(U *).
所以我的问题是,在一个特定平台上给出一个特定的实用编译器(不包括假设的Hell),是否有理由期望所有指向非联合类类型的指针都具有相同的大小?或者是否有一个实际的原因,为什么编译器可能希望使用不同的大小,同时保持符合协变返回类型?
在存在指针的不同“级别”的平台上(例如__near和__far),假设应用于两者的相同属性.
解决方法
6.2.5 Types
27 […] All pointers to structure types shall have the same representation and alignment requirements as each other. […]
C有效地需要与C实现的二进制兼容性,因为标准对extern“C”的要求,所以间接地,这需要所有指向结构类型的指针,这些结构类型在C(POD类型,相当多)中有效,以具有相同的表示和对齐在C中也是如此.
似乎没有对非POD类型做出这样的要求,因此在这种情况下允许实现使用不同的指针大小.你建议那不行,但要按照你的例子,
struct G { }; struct H : G { }; struct W { virtual G* f() { ... } }; struct X : W { virtual H* f() { ... } };
可以翻译成(伪代码)
struct W { virtual G* f() { ... } }; struct X : W { override G* f() { ... } inline H* __X_f() { return static_cast<H *>(f()); } };
这仍然符合语言的要求.
两个指向结构类型的指针可能不相同的一个正当理由是,当C编译器被移植到具有设计不良的ABI的现有C编译器的平台时. G是POD类型,因此G *必须与C中的完全相同.H不是POD类型,因此H *不需要匹配任何C类型.
对于对齐,这实际上可能发生:真正发生的事情是典型的GNU / Linux系统上的x86-32 ABI需要64位整数类型才能进行32位对齐,即使处理器的首选对齐实际上是64位.现在又出现了另一个实现者,他们认为他们确实需要64位对齐,但如果他们想要与现有实现保持兼容,则会陷入困境.
对于尺寸,我想不出它会发生的合理情况,但我不确定这是否可能是我缺乏想象力.