我遇到了一种我无法理解的非常奇怪的行为。我有一个Texture
类,其contentWidth
属性类型为int
。此类包含在Image
类中,该类具有类型为width
的{{1}}属性。 int
的{{1}}仅计算为基础纹理的width
:
Image
现在contentWidth
被- (int) width
{
return texture.contentWidth;
}
类(通过合成,而不是继承)用于想要读取图像大小的内容:
Image
问题是Button
变量设置得很好,而// image is of type ‘id’
int width = [image width];
int height = [image height];
变量包含height
(-2147483648)。我检查了尺寸 - 它们大约是200×100左右,远不到width
极限。此外,Xcode调试器工具提示正确显示NaN
中的两个属性,只有在宽度通过两个访问器后,数字才会出现乱码。对象未释放。我错过了什么?
更新:我已在int
类中扩展了访问者,以查看问题的来源:
Texture
现在,当我在第一行中断时,Image
被正确设置。我跳了过去,执行返回到调用函数:
- (int) width
{
const int w = texture.contentWidth;
return w;
}
...现在w
包含- (void) foo
{
int bar = [image width];
}
。
更新:嗯,明白了:
bar
NaN
被声明为int foo = [image width]; // image is id, returns NaN
int bar = [(Image*) image width]; // correct value
,这就是这里的要点。有人可以解释一下吗?我有一种感觉,我没有使用正确的image
方法,但这究竟是怎么回事?我总是尽可能严格地输入我的变量,但这里的id
类型很方便。我不知道它会导致这样的错误。
答案 0 :(得分:5)
一般来说,方法不同 具有相同选择器的类 (同名)也必须分享 相同的返回和参数类型。这个 约束由编译器强加 允许动态绑定。因为 消息接收器的类(和 因此,特定于类的细节 它被要求执行的方法), 在编译时无法知道的 编译器必须处理所有方法 同名的人。准备的时候 方法返回和信息 运行时系统的参数类型, 它只创建一个方法描述 对于每个方法选择器。
然而,当一条消息被发送到 静态类型对象,类 接收器是编译器已知的。 编译器可以访问 有关的特定类别信息 方法。因此,消息是 摆脱对它的限制 返回和参数类型。
这是GCC bugzilla中的bug report(以及相应的blog post)。行为不是错误,但它也不是很友好,因为编译器不会警告你(至少没有默认的警告设置)。
答案 1 :(得分:1)
你的访问者不应该是:
- (int) width
{
return [texture contentWidth];
}
纹理是实例变量吗?如果是,你是否使用init方法或你的包装类来初始化它?