2013-11-22 2 views
2

настоящее время у меня этот код:Как написать объявление свойства для массива C в ObjC?

@interface Matrix4 : NSObject 
{ 
    float mat[16]; 
} 
@property (readonly) float mat[1]; 

Я хочу собственности либо дать мне массив мат или несколько свойств, давая мне доступ только для чтения к циновке [1], мат [2] и т.д.

I current have "Свойство не может иметь массив типа функции float [1]" в качестве сообщения об ошибке

ответ

5

Массивы не могут возвращать значения, поэтому свойство не может иметь тип массива. Вместо этого вы должны вернуть указатель, объявите свойство как указатель на тип элемента массива:

@property (readonly) float *mat; 

Держите переменный экземпляр в качестве float mat[16] как вы едите сейчас. Затем осуществить аксессор, чтобы вернуть указатель на массив:

- (float *)mat { 
    return mat; // array decays to pointer automatically 
} 

В качестве альтернативы, вы можете иметь аксессора непосредственно для отдельных элементов:

- (float)matIndex:(NSUInteger)i { 
    // maybe check bounds here? 
    return mat[i]; 
} 

Проблема с этими подходами в том, что информация о размер массива теряется, поэтому вы, вероятно, захотите поместить размер массива в макрос или переменную const. Если вам нужно что-то более объектно-ориентированное, сделайте массив NSArray и сохраните в нем NSNumber s.

редактировать: Один из вариантов будет также обернуть массив в struct, чтобы сохранить информацию о размере, хотя вы все еще, вероятно, хотите, чтобы передать его вокруг по ссылке:

struct matrixf16 { 
    float f[16]; 
}; 
@interface Matrix4 : NSObject { 
    struct matrixf16 mat; 
} 
@property (readonly) struct matrixf16 *mat; 

(Кроме того, если я «Предполагаю, что размер равен 16, потому что он предназначен для хранения матрицы размером 4 × 4, почему бы не сделать массив float f[4][4].)

+0

В первом предложении, которое вы даете, я получаю сообщение об ошибке «Тип свойства« мат »('float *') не соответствует типу переменной экземпляра 'mat' ('float [16]')", когда я пытаюсь для @synthesize. Или я не должен синтезировать его? Это произошло после удаления (только для чтения). Я предполагаю, что мне действительно нужно это как только для чтения, потому что есть много способов, по которым я хочу, чтобы матрица была настроена так, поэтому мне нужны специальные методы настройки с описательными именами. –

+0

Также в чем разница между использованием float [16] и float [4] [4]? –

+0

@MartiMarkov Да, не '@ синтезируйте', когда есть несоответствие. Разница между «[16]» и «[4] [4]» заключается в том, что последний передает значение двумерной матрицы 4 × 4, к которой можно получить доступ «mat [y] [x]», тогда как первая будет 'mat [y * 4 + x]'. – Arkku

1

Как компилятор говорит вам, что свойства не могут иметь тип массива или функции.

Вы можете вручную осуществить сорбент, как

@interface Matrix4 : NSObject { 
    float mat[16]; 
} 
- (float *)mat; 

@implementation 
- (float *)mat { 
    return mat; 
} 

или вы можете рассмотреть возможность использования NSArray вместо этого, в зависимости от ваших требований. NSArray определенно имеет избыточный вес, чем собственный массив C, но он позволяет использовать свойства.


Однако я подозреваю, что у Вас есть вопрос дизайна: он выглядит, как вы пытаетесь реализовать прямоугольную матрицу, но вы подвергаете внутреннее представление, скорее всего, так что клиент может установить матричные элементы.

Вы должны скрыть внутреннее представление и только разоблачить методы для выполнения операций с матрицами.Например, вы можете думать о обнажая метод, который устанавливает значение матрицы, как:

- (void)setValue:(float)value forRow:(int)row column:(int)col { 
    NSParameterAssert(row >= 0 && row < 4 && col >= 0 && col < 4) 
    mat[row * 4 + col] = value; 
} 

и тот, который дает вам элемент назад

- (float)valueForRow:(int)row column:(int)col { 
    NSParameterAssert(row >= 0 && row < 4 && col >= 0 && col < 4) 
    return mat[row * 4 + col]; 
} 

и сделать mat Ивар приватным. Это дает вам также гибкость изменения внутреннего представления по своему усмотрению, не нарушая код клиента.

Вышеупомянутая реализация также очень легко обобщается на квадратную матрицу размера, предоставляя параметр измерения и используя NSArray или динамическое распределение памяти (поскольку массивы переменной длины не могут быть ivars).

+0

Мне не нравится идея 'NSArray' для этого случая, потому что вы не можете ограничить его длину. и он имеет избыточный вес, чем массив C –

+0

@BryanChen у него есть верхние и нижние стороны, один из которых - способность использовать свойство. В зависимости от требований это может быть лучший или худший выбор, но без дальнейших подробностей трудно сказать. –

Смежные вопросы