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



我使用Stephen Kochan在其著作《Objective-C编程,第4版》中的例子来学习使用基于Windows的GNUstep环境的程序语言。我使用的是gnustep mysys-system-0.29.0、gnustepcore-0.29.0和gnustepdevel-1.4.0安装。

现在来看Kochan书的第三章中的程序。当我执行源代码时,我为两个unqiue对象打印出相同的实例变量值,"frac1"one_answers"frac2"。"frac1"对象的实例变量numerator和分母的内存位置似乎引用了"frac2"对象的相同内存位置。

当我在"frac2"中将分子设置为3,将分母设置为7时,"frac1"中的分子和分母会被覆盖。为什么?我不知道为什么?。当打印"frac1"one_answers"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;
}

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

您已经注释掉了围绕numeratordenominator声明的{}。我猜你这样做是因为你把大括号留在中时遇到了编译器错误

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

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

有一个新的GNU Objective-C运行时确实支持这一功能,但GNU编译器不支持。你必须将苹果的编译器(clang)与新的GNU运行时一起使用。我不知道在Windows上运行这个设置有多容易。

你可以在这里了解更多关于这场混乱的信息:http://wiki.gnustep.org/index.php/ObjC2_FAQ

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

您的问题是在类的@实现中而不是在@接口中声明分子和分母值。这使它们成为全局变量,而不是类的实例变量。更新你的界面如下:

@interface Fraction:NSObject {
   int numerator;
   int denominator;
 }
 - (void)print;
 -(void) setNumerator: (int) n;
 -(void) setDenominator: (int) d;
@end

然后从@implementation部分中删除声明。然后它应该按照您期望的方式运行。

问题是Fraction的两个实例变量numeratordenominator实际上并没有被声明为实例变量,而是被声明为全局变量。您应该在@接口中声明它们,如下所示:
@interface Fraction:NSObject
{
  int numerator;
  int denominator;
}
 -(void)print;
 -(void) setNumerator: (int) n;
 -(void) setDenominator: (int) d;
@end

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

最新更新