Objective c -forwardInvocation可用于Clang-LLVM,但不能用于GCC

Objective c -forwardInvocation可用于Clang-LLVM,但不能用于GCC,objective-c,gcc,llvm,clang,Objective C,Gcc,Llvm,Clang,下面的代码实现了一个NSProxy子类,该子类将方法转发给NSNumber实例 但是,在调用[nsproxy floatValue]时,我在GCC4.2下得到了0.0 在LLVM Clang下,我得到了正确答案42.0 知道发生了什么吗 (顺便说一下,这是在垃圾收集下运行的) 您的代理类没有为-floatValue声明消息签名。由于它返回一个浮点数,这可能是一个问题。因为您没有在任何地方声明它,并且可能没有将代理对象强制转换到它的“表示类”,所以编译器必须猜测方法签名。在这种情况下,GCC编译器

下面的代码实现了一个NSProxy子类,该子类将方法转发给NSNumber实例

但是,在调用[nsproxy floatValue]时,我在GCC4.2下得到了0.0

在LLVM Clang下,我得到了正确答案42.0

知道发生了什么吗

(顺便说一下,这是在垃圾收集下运行的)


您的代理类没有为
-floatValue
声明消息签名。由于它返回一个浮点数,这可能是一个问题。因为您没有在任何地方声明它,并且可能没有将代理对象强制转换到它的“表示类”,所以编译器必须猜测方法签名。在这种情况下,GCC编译器猜测消息将返回一个
id
指针

在Objective-C中,根据消息的签名和机器的体系结构,可以使用不同的函数来处理消息及其返回值。在x86机器上,返回浮点值的消息通过
objc\u msgSend\u fpret
调用,而返回
void
id
的函数使用
objc\u msgSend

由于GCC编译器假定返回值是一个
id
,因此它使用后一个函数并错误地处理结果。叮当声能够正确处理这一点很有趣,但我会犹豫是否依赖于这种行为。最好在您的代理上为您要转发的任何方法声明一个类别。这还有一个好处,即删除为调用
floatValue
方法的代码行生成的警告

@interface Foo (ProxyMethods)
- (float)floatValue;
@end

任何
init
方法都应该调用
[super init]以防止意外行为。因此:

- (id)init {
    self = [super init];
    if (self) {
        // Your init code
    }
    return self;
}

感谢您清楚地解释了答案,我认为这与期望id指针返回为float有关。只是没有看到任何关于潜在陷阱的苹果文档。Nproxy没有init方法。
- (id)init {
    self = [super init];
    if (self) {
        // Your init code
    }
    return self;
}