我使用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;
}
//========================
您已经注释掉了围绕numerator
和denominator
声明的{
和}
。我猜你这样做是因为你把大括号留在中时遇到了编译器错误
我推断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
的两个实例变量numerator
和denominator
实际上并没有被声明为实例变量,而是被声明为全局变量。您应该在@接口中声明它们,如下所示:
@interface Fraction:NSObject
{
int numerator;
int denominator;
}
-(void)print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
@end
全局变量可以由程序的任何部分查看和设置。当您在类的@interface部分中将变量声明为实例变量时,类的每个实例都会获得自己的一组变量,而其他实例无法直接查看/更改它们。