2011-02-04 8 views
0

スーパークラスとしてオブジェクトを送信した後、サブクラスのメンバー変数にアクセスすることはできません。メンバー関数が機能しています。この例を参照してください:スーパークラスとして送信した後、サブクラスのメンバーにアクセスできない

スーパークラス定義

@interface SuperClass : NSObject { 
NSString *stringSuper; 
NSInteger intSuper; 
} 
- (void)test; // NSLog(@"test: SuperClass"); 

派生クラス定義

@interface DerivedClass : SuperClass { 
NSString *stringDerived; 
NSInteger intDerived; 
} 
- (void)test; // NSLog(@"test: DerivedClass"); 
- (void)test1; // NSLog(@"test1: DerivedClass"); 

へキャストした後のアクセスのメンバーにしてみてくださいDerivedClassオブジェクトを作成し、スーパークラス

DerivedClass *d = [[DerivedClass alloc] init]; 
d.stringSuper = anotherString; 
d.intSuper = anotherInt; 
d.stringDerived = anotherString1; 
d.intDerived = anotherInt1; 

[anObject sendMessage:d]; 

として送信DerivedClass

- (void)sendMessage:(SuperClass *)s { 
DerivedClass *d = (DerivedClass *)s; 
NSLog(@"%@", d.stringSuper); // ok 
NSLog(@"%d", d.intSuper); // ok 
NSLog(@"%@", d.stringDerived); // EXC_BAD_ACCESS 
NSLog(@"%d", d.intDerived); // ok 

[d test]; // ok ("test DerivedClass") 
[d test1]; // ok ("test1 DerivedClass") 
} 

私はすべてのメンバーに対して@properties(非原子、代入)を宣言しました。デバッガは、stringDerivedの正しいアドレスを表示しますが、「範囲外です」。

誰もがこの動作の理由を知っていますか?

おかげで、RODO

+0

anotherString1変数 – Robin

+0

を初期化したコードを投稿する(非原子的、保持)にプロパティを変更すると、クラッシュは消えますか?返信いただきありがとうございます。 – fbrereto

+0

@robinすべての文字列は同じ方法で初期化されます([NSString stringWithFormat:@ "..."])。彼らはデリゲートのコールバックから来ます。 – user602313

答えて

1

はい:あなたはhow to do propertiesのルール1に違反しています。明らかに、anotherString1はd.stringDerivedから読み込んだポイントの前にリリースされました。 d.stringDerivedを設定した時点で無効になっている可能性もあります。同様に、anotherStringは明らかに定数文字列か、何か他のものによって保持されています。実際のコードを表示していればもっと明らかになっていました。

オブジェクト型プロパティでクラスを定義する場合は、クラスのインスタンスがそのプロパティに割り当てられた値をコピーまたは保持して、次に見たときにそのプロパティが存在することを保証する必要があります。 assignを使用すると、値はおそらくオートレリースされた値になる可能性があるため、非常に迅速に無効になります。一般に、プロパティタイプがNSCopyingプロトコルに準拠していて、それが変更可能であるか、または変更可能なサブクラス(NSString、NSData、NSSet、NSArrayなど)を持つ場合は、copyを使用して値が一度変更されないようにするのが最適ですセット;他のケースでは、retainを使用するのは問題ありません。

このようにすると、オブジェクトの割り当てが解除されたときに、プロパティ値で使用されるメモリが正しく考慮されていることも確認する必要があります。 deallocルーチンのオブジェクト型プロパティの値をnilに設定します。

+0

ありがとうございます - 私はプロパティのコピー/保持を使用しようとしましたが、私は[[NSString alloc] initWithFormat:]の代わりに[NSString stringWithFormat:]を使用して文字列を初期化しました。今それは動作します - もう一度ありがとう! – user602313

+0

stringWithFormat:保持され、オートレリースされた文字列を返します。保持カウントは1になり、すぐに0になります。 alloc/initWithFormat:オートレリースされていない文字列を返します。保持カウントは1で、明示的に解放されるまで1のままです。ビルドと分析を使用して、コンパイル時に保持/解放が合理的であることを確認し、実行時にリークツールでチェックすることができます。 –

関連する問題