我应该如何在ObjC中为C数组写一个属性声明?

时间:2013-11-22 02:46:46

标签: objective-c arrays

我目前有这段代码:

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

我希望该属性要么给我mat数组,要么有多个属性让我只能访问mat [1],mat [2]等。

我当前有“属性不能有函数类型float [1]”作为错误消息

2 个答案:

答案 0 :(得分: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存储在其中。

编辑:一个选项也是将数组包装在struct中以保留大小信息,但您仍然可能希望通过引用传递它:

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

(另外,如果我正确猜测大小是16,因为它意味着要保持4×4矩阵,为什么不制作数组float f[4][4]。)

答案 1 :(得分:1)

正如编译器告诉你的那样,属性不能有数组或函数类型。

您可以手动实现getter,例如

@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 ivar设为私有。这使您可以灵活地随意更改内部表示,而不会破坏客户端的代码。

通过提供维度参数并使用NSArray或动态内存分配(因为可变长度数组不能是ivars),上述实现也很容易推广到大小的平方矩阵。