2012-02-17 7 views
2

私はStephen Kochanの例「Programming in Objective-C、Edition 4」を使って、WindowsベースのGNUstep環境を使ってプログラム言語を学んでいます。私はgnustep mysys-system-0.29.0、gnustep-core-0.29.0とgnustep-devel-1.4.0のインストールを使用しています。なぜ2つの一意のオブジェクトのインスタンス変数がメモリの場所を参照していますか?

今、コチャンの本の第3章のプログラムに。 ソースコードを実行すると、2つのunqiueオブジェクトの同じインスタンス変数値、 'frac1'と 'frac2'が表示されます。 'frac1'オブジェクトのインスタンス変数のメモリ位置は、 'frac2'オブジェクトの同じメモリ位置を参照するように見えます。

'frac2'で分子を3に、分母を7に設定すると、 'frac1'の分子と分母が上書きされます。どうして?何故かはわからない?。私は、 'frac1'と 'frac2'の一意のインスタンス変数を印刷するときに同じ分数3/7を表示します。以下は

は、私がコンパイルしたソースプログラムである:

//======================== 
// ##copied from "Programming in Objective C" pages 30-44 - edition 4 


#import <Foundation/Foundation.h> 


// --- @interface section ---- 

@interface Fraction:NSObject 

- (void)print; 
-(void) setNumerator: (int) n; 
-(void) setDenominator: (int) d; 

@end 


//[email protected] 


#include <stdio.h> 
@implementation Fraction 
//{ 


    int numerator; 
    int denominator; 
//} 

- (void)print 
{ 
    NSLog (@"%i/%i", numerator, denominator); 
} 

-(void) setNumerator: (int) n 
{ 
    numerator = n; 
} 

-(void) setDenominator: (int) d 
{ 
    denominator = d; 
} 

@end 

//--- program section ---- 


int main(int argc, const char * argv[]) 
{ 


    //Fraction *myFraction; 

    // Create an instance of a Fraction 

    //myFraction = [Fraction alloc]; 
    //myFraction = [myFraction init]; 

    Fraction *frac1; 
    frac1 = [Fraction alloc]; 
    frac1 = [frac1 init]; 

    Fraction *frac2 = [[Fraction alloc] init]; 

    // Set 1st fraction to 2/3 

    [frac1 setNumerator: 2]; 
    [frac1 setDenominator: 3]; 


    // Set 2nd fraction to 3/7 

    [frac2 setNumerator: 3]; 
    [frac2 setDenominator: 7]; 

    // Display the fractions 

    // 'frac1' print should display fraction 2/3, however 3/7 is displayed 

    NSLog (@"first print is:"); 
    [frac1 print]; 

    // 'frac2' print displays fraction 3/7, as expected. 

    NSLog (@"second print is:"); 
    [frac2 print]; 

    return 0; 
} 


//======================== 

答えて

2

あなたの問題は、あなたがクラスの@implementationではなく@interfaceで分子と分母の値を宣言することです。これにより、クラスのインスタンス変数ではなくグローバル変数になります。インターフェイスを次のように更新してください:

@interface Fraction:NSObject { 
    int numerator; 
    int denominator; 
} 

- (void)print; 
-(void) setNumerator: (int) n; 
-(void) setDenominator: (int) d; 

@end 

@implementationセクションから宣言を削除してください。それはあなたが期待しているように動作するはずです。

+0

ありがとうございました。ここでは、インスタンス変数を実装セクションからインターフェイスセクションに移動しました。 –

2

Fractionの2つのインスタンス変数numeratordenominatorは、実際にはインスタンス変数として宣言されず、グローバルとして宣言されています。

グローバル変数は、プログラムのどの部分でも確認できます。クラスの@interfaceセクションで変数をインスタンス変数として宣言すると、クラスの各インスタンスはそれらの変数のセットを取得し、他のインスタンスはそれらを直接表示/変更することはできません。

+0

ありがとう、私はインスタンス変数を実装セクションからインターフェイスセクションに移動したので、すべて動作します。 –

3

numeratordenominatorの宣言を囲んで{}をコメントアウトしました。私が推測するのは、あなたが中括弧を残したときにコンパイラエラーが発生したからです。

Appleの現在のObjective-Cコンパイラとランタイムを使用するプログラマ向けに、KoOSの本がiOSと64ビットMac OSこれは、「新しいランタイム」または「現代ランタイム」とも呼ばれます。このバージョンのコンパイラとランタイムには、「脆弱でないインスタンス変数」と呼ばれる機能があります。これにより、インスタンス変数をクラスインタフェースではなく、クラス実装に入れることができます。 Kochanのコードでは、この非脆弱なインスタンス変数の機能が使用されています。

使用しているGNUコンパイラとランタイムは、この機能をサポートしていません。

この機能をサポートする新しいGNU Objective-Cランタイムがありますが、GNUコンパイラはこの機能をサポートしていません。新しいGNUランタイムでAppleのコンパイラ(clang)を使用する必要があります。私は、Windows上で動作するセットアップがどれほど簡単であるかわかりません。http://wiki.gnustep.org/index.php/ObjC2_FAQ

回避策は、あなたのインターフェイスであなたのインスタンス変数を宣言することです:

あなたはここにこの混乱についての詳細を学ぶことができます。 Tim DeanとAndrew Madsenの答えは構文を示しています。

+0

偉大な答え、ロブ。私は答えを投稿したときに何が問題を引き起こしているのか分かっていましたが、非壊れやすいインスタンスについてはわかりませんでしたし、インスタンス変数を自分の@implementationに移すという選択肢もありました。今私はこれを知っているので、私はすべてのインスタンス変数を動かすかもしれないと思う! –

+0

私は非壊れやすいインスタンス変数を♡。 –

+0

ありがとう、ここでは、インスタンス変数を実装セクションからインターフェイスセクションに移動したところですべて動作します。 –

関連する問題