【问题标题】:Can't acces members of a sub class after sending as super class作为超类发送后无法访问子类的成员
【发布时间】:2011-06-21 05:07:40
【问题描述】:

将对象作为超类发送后,我无法访问子类的成员变量。成员函数正在工作。看这个例子:

超类定义

@interface SuperClass : NSObject {
 NSString *stringSuper;
 NSInteger intSuper;
}
- (void)test; // NSLog(@"test: SuperClass");

派生类定义

@interface DerivedClass : SuperClass {
 NSString *stringDerived;
 NSInteger intDerived;
}
- (void)test; // NSLog(@"test: DerivedClass");
- (void)test1; // NSLog(@"test1: DerivedClass");

创建一个 DerivedClass 对象并作为 SuperClass 发送

DerivedClass *d = [[DerivedClass alloc] init];
d.stringSuper = anotherString;
d.intSuper = anotherInt;
d.stringDerived = anotherString1;
d.intDerived = anotherInt1;

[anObject sendMessage:d];

在转换为 DerivedClass 后尝试访问成员

- (void)sendMessage:(SuperClass *)s {
 DerivedClass *d = (DerivedClass *)s;
 NSLog(@"%@", d.stringSuper); // ok
 NSLog(@"%d", d.intSuper); // ok
 NSLog(@"%@", d.stringDerived); // EXC_BAD_ACCESS
 NSLog(@"%d", d.intDerived); // ok

 [d test]; // ok ("test DerivedClass")
 [d test1]; // ok ("test1 DerivedClass")
}

我已经为所有成员声明了@properties(非原子,赋值)。调试器向我显示了 stringDerived 的正确地址,但它“超出范围”。

有人知道这种行为的原因是什么吗?

谢谢,罗多

【问题讨论】:

  • 发布初始化 anotherString1 变量的代码,
  • 如果将属性更改为 (nonatomic, retain) 崩溃会消失吗?
  • @robin 感谢您的回复。所有字符串都以相同的方式初始化(​​[NSString stringWithFormat:@"..."])。它们来自委托的回调。
  • 为了记录,在 Objective-C 的说法中,这些是 instance 变量。
  • @fbrereto 感谢您的重播。我已经尝试过这个 - (非原子,保留)的相同行为。

标签: objective-c subclass member


【解决方案1】:

是的:您违反了how to do properties 的规则 1。显然anotherString1 在您从 d.stringDerived 读取的点之前发布;它甚至可能在您设置 d.stringDerived 时无效。同样,anotherString 显然是一个常量字符串或被其他东西保留。如果你展示了你的实际代码会更明显。

如果您定义一个具有对象类型属性的类,则必须安排类的实例复制或保留分配给该属性的值,以确保下次查看时它仍然存在。如果您使用 assign 该值可能会很快变得无效,因为它很可能是一个自动释放的值。一般来说,如果属性类型符合 NSCopying 协议并且它是可变的或具有可变的子类(例如:NSString、NSData、NSSet、NSArray 等),最好使用复制,这样值就不会改变一次放;在其他情况下,使用保留很好。

完成此操作后,您还必须确保在释放对象时正确计算属性值使用的内存。在您的 dealloc 例程中将任何对象类型属性的值设置为 nil。

【讨论】:

  • 非常感谢 - 我尝试对属性使用复制/保留,但我总是使用 [NSString stringWithFormat:] 而不是 [[NSString alloc] initWithFormat:] 来初始化字符串。现在它可以工作了 - 再次感谢!
  • stringWithFormat:返回一个保留并自动释放的字符串 - 保留计数为 1,很快将变为 0; alloc/initWithFormat:返回一个保留的未自动释放的字符串 - 保留计数为 1,在显式释放之前将保持为 1。使用 Build and Analyze 帮助您在编译时检查您的保留/释放是否合理,并使用 Leaks 工具运行以在运行时检查它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-25
  • 2012-12-01
  • 2013-06-08
  • 2018-07-22
  • 2012-09-15
  • 2011-02-18
  • 2023-04-04
相关资源
最近更新 更多