Почему переменные экземпляра двух уникальных объектов ссылаются на ячейку памяти? - PullRequest
2 голосов
/ 18 февраля 2012

Я использую примеры Стивена Кочана в своей книге «Программирование в Objective-C, выпуск 4» для изучения языка программы с использованием среды GNUstep на основе Windows. Я использую gnustep mysys-system-0.29.0, gnustep-core-0.29.0 и gnustep-devel-1.4.0.

Теперь к программе в главе 3 книги Кочана. Когда я выполняю исходный код, Я получаю одинаковые значения переменных экземпляра, распечатанные для двух unqiue объектов, 'frac1' и 'frac2'. Похоже, что области памяти объекта 'frac1' для числовых переменных и знаменателя переменных ссылаются на те же области памяти для объекта 'frac2'.

Когда я устанавливаю числитель на 3 и знаменатель на 7 в 'frac2', числитель и знаменатель в 'frac1' перезаписываются. Зачем? Я не знаю почему?. Я получаю ту же дробь 3/7, отображаемую при печати уникальных переменных экземпляра для 'frac1' и 'frac2'.

Ниже приведена исходная программа, которую я скомпилировал:

//========================
// ##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 ]

3 голосов
/ 18 февраля 2012

Вы закомментировали { и }, окружающие объявления numerator и denominator.Я предполагаю, что вы сделали это, потому что вы получали ошибки компилятора, когда оставляли скобки.

Я делаю вывод, что книга Кочана написана для программистов, использующих текущий компилятор Apple Objective-C и время выполнения, для iOS и 64-битныхMac OS X. Это также называется «новым временем выполнения» или «современным временем выполнения».Эта версия компилятора и среды выполнения имеет функцию, называемую «хрупкие переменные экземпляра», которая позволяет вам помещать переменные вашего экземпляра в реализацию вашего класса, а не в интерфейс вашего класса.Код Кочана использует эту не хрупкую переменную экземпляра.

Компилятор GNU и используемая среда выполнения не поддерживают эту функцию.

Существует новая среда выполнения GNU Objective-C, которая делаетподдерживает эту функцию, но компилятор GNU не поддерживает ее.Вам придется использовать компилятор Apple (clang) с новой средой исполнения GNU.Я не знаю, насколько легко заставить эту настройку работать в Windows.

Подробнее об этом беспорядке можно узнать здесь: http://wiki.gnustep.org/index.php/ObjC2_FAQ

Обходной путь - объявить переменные вашего экземпляра вваш интерфейсОтветы Тима Дина и Эндрю Мэдсена показывают синтаксис.

2 голосов
/ 18 февраля 2012

Проблема в том, что две переменные экземпляра Fraction, numerator и denominator, фактически не объявляются как переменные экземпляра, а объявляются как глобальные. Вы должны объявить их в @interface следующим образом:

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

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

@end

Глобальные переменные могут быть просмотрены и установлены любой частью вашей программы. Когда вы объявляете переменные как переменные экземпляра в разделе @interface вашего класса, каждый экземпляр класса получает свой собственный набор этих переменных, а другие экземпляры не могут видеть / изменять их напрямую.

2 голосов
/ 18 февраля 2012

Ваша проблема в том, что вы объявляете значения числителя и знаменателя в @implementation класса, а не в @interface.Это превращает их в глобальные переменные, а не в переменные экземпляра для вашего класса.Обновите свой интерфейс так, чтобы он был таким:

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

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

@end

, а затем удалите объявления из раздела @implementation.Затем он должен вести себя так, как вы ожидаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...