这是一小段代码。由俄罗斯公司Yandex发布,作为他们采访的一部分。这里有什么潜在的问题?它看起来很简单,应该是我看不到的隐藏问题。
第一个标题
//Foo.h
#import <Cocoa/Cocoa.h>
@interface Foo : NSObject
{
NSString* str;
static int i = 0;
}
- (NSString*) str;
@end
另一个档案
//Foo.m
#import "Foo.h"
@implementation
- (id) init
{
return [self initWithStr:"number:" someInt:6];
}
- (id) initWithStr:(NSString*)theStr someInt:(int)value
{
self = [super init];
str = [NSString stringWithFormat:@"%@%d", theStr, value];
return self;
}
- (NSString*) str
{
return str;
}
- (void) setStr:(NSString*)theStr
{
str = theStr;
}
@end
最后一个文件
//main.m
#import <Cocoa/Cocoa.h>
#import "Foo.h"
int main(int argc, char *argv[])
{
Foo objA;
NSLog([objA str]);
[objA setStr:@"hello world!"];
NSLog([objA str]);
Foo* objB = [[Foo alloc] init];
Foo* objC = [[Foo alloc] initWithStr:@"My magic number:" value:265];
objB = objC;
NSLog([objB str]);
[objA release];
[objB release];
[objC release];
return 0;
}
答案 0 :(得分:6)
在另一个档案中:
@implementation
执行什么?必须指定。
在最后一个文件中:
Foo objA;
NSLog([objA str]);
[objA setStr:@"hello world!"];
NSLog([objA str]);
这会崩溃,本地变量Foo objA没有被初始化,它可以设置为nil,因为在目标c中,nil的消息是正常的,但事实并非如此。
下面:
[objA setStr:@"hello world!"];
该方法将发出编译警告,因为该方法未在接口中声明,但它仍将调用该方法。
下面:
- (id) init
{
return [self initWithStr:"number:" someInt:6];
}
字符串@“number:”
缺少@下面:
objB = objC;
你刚刚泄露了objB,因为现在没有有效的引用来释放之前的分配。
[objA release];
这从未分配过!
[objB release];
[objC release];
第二个会崩溃,因为它们都引用同一个对象,并且保留计数只有1。
第一个文件也有一些潜在的问题,例如声明一个似乎是getter的方法而没有声明ivar的属性,与setter相同,最好只声明一个属性。
答案 1 :(得分:1)
@interface Foo : NSObject
{
NSString* str;
static int i = 0;
}
您无法在此处定义static int i = 0;
。类型名称不允许指定存储类Foo.h
答案 2 :(得分:0)
此外,setter需要释放前一个字符串并保留新字符串。
- (void) setStr:(NSString*)theStr
{
if(str) {
[str release];
}
str = [theStr retain];
}