4

次のコードは、メソッドをNSNumberインスタンスに転送するNSProxyサブクラスを実装します。

ただし、[nsproxy floatValue]を呼び出すと、GCC4.2では0.0になります。

LLVM-Clangでは、正解42.0が得られます。

何が起こっているのか分かりますか?

(ちなみに、これはガベージコレクションの下で実行されています)

-(id) init;
{
    _result = [NSNumber numberWithFloat:42.0];
    return self;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    return [[_result class] instanceMethodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    [anInvocation setTarget:_result];
    [anInvocation invoke];
    return;
} 
4

2 に答える 2

6

プロキシ クラスは のメッセージ署名を宣言していません-floatValue。浮動小数点数を返すため、問題になる可能性があります。どこにも宣言しておらず、おそらくプロキシオブジェクトをその表現されたクラスにキャストしていないため、コンパイラはメソッドシグネチャを推測する必要があります。idその場合、GCC コンパイラはメッセージがポインタを返すと推測します。

Objective-C では、メッセージの署名とマシンのアーキテクチャに応じて、メッセージとその戻り値の処理にさまざまな関数が使用されます。x86 マシンでは、浮動小数点値を返すメッセージは、を返して使用するobjc_msgSend_fpretwhile 関数を通じて呼び出されます。voididobjc_msgSend

GCC コンパイラは戻り値が であると想定しているためid、後者の関数を使用し、結果を誤って処理します。Clang がこれを適切に処理できるのは興味深いことですが、その動作に頼るのはためらわれます。転送するすべてのメソッドについて、プロキシでカテゴリを宣言することをお勧めします。これには、メソッドを呼び出すコード行に対して生成されていた警告を削除するという利点もありますfloatValue

@interface Foo (ProxyMethods)
- (float)floatValue;
@end
于 2009-09-21T07:10:52.487 に答える
-1

予期しない動作を防ぐために、すべてのinitメソッドを呼び出す必要があります。[super init];そのとおり:

- (id)init {
    self = [super init];
    if (self) {
        // Your init code
    }
    return self;
}
于 2012-03-10T23:28:44.233 に答える