为什么两个唯一对象的实例变量引用内存位置?

时间:2012-02-17 21:38:11

标签: objective-c object methods

我正在使用Stephen Kochan在他的“Objective-C,Programming 4编程”一书中使用基于Windows的GNUstep环境学习程序语言的例子。我正在使用gnustep mysys-system-0.29.0,gnustep-core-0.29.0和gnustep-devel-1.4.0安装。

现在参加Kochan书中第3章的节目。当我执行源代码时, 我得到两个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


//----@implementation----


#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;
}


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

3 个答案:

答案 0 :(得分:3)

您已对{}的声明周围的numeratordenominator进行了评论。我猜你是这样做的,因为当你离开大括号时你会遇到编译器错误。

我推断Kochan的书是为使用Apple目前的Objective-C编译器和运行时的程序员编写的,适用于iOS和64位Mac OS X.这也称为“新运行时”或“现代运行时”。此版本的编译器和运行时具有一个名为“非脆弱实例变量”的功能,它允许您将实例变量放在类实现中,而不是在类接口中。 Kochan的代码使用了这个非脆弱的实例变量功能。

您使用的GNU编译器和运行时不支持此功能。

有一个新的GNU Objective-C运行时支持此功能,但GNU编译器不支持它。你必须使用Apple的编译器(clang)和新的GNU运行时。我不知道在Windows上使用该设置是多么容易。

您可以在此处了解有关此问题的更多信息:http://wiki.gnustep.org/index.php/ObjC2_FAQ

解决方法是在界面中声明实例变量。 Tim Dean和Andrew Madsen的答案显示了语法。

答案 1 :(得分:2)

你的问题是你在类的@implementation而不是@interface中声明了分子和分母值。这使它们成为全局变量而不是您的类的实例变量。将您的界面更新为:

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

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

@end

然后从@implementation部分删除声明。然后它应该像你期望的那样表现。

答案 2 :(得分:2)

问题是Fraction的两个实例变量numeratordenominator实际上并未声明为实例变量,而是将它们声明为全局变量。您应该在@interface中声明它们,如下所示:

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

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

@end

全局变量可以由程序的任何部分查看和设置。当您在类的@interface部分中将变量声明为实例变量时,该类的每个实例都会获得自己的一组变量,而其他实例则无法直接查看/更改它们。