[英]Objective C init method and inheritance
我有2个A和B类,B继承自A,A继承自NSObject.Class A有一个函数 - (void)init:
- (void)init {
if (self = [super init]) {
NSLog(@"A");
}
return self;
}
B有:
- (id)init {
if (self = [super init]) {
NSLog(@"B");
}
return self;
}
编译后我在我的控制台中有“A”和“B”,尽管B中的条件“if(self = [super init])”不能为真,导致其超类init方法返回void。任何想法?
PS我知道init方法必须返回id,我很感兴趣,为什么这样做有效,而不应该。
您通过分配void函数调用的结果来调用未定义的行为。 未定义的行为意味着几乎任何事情都可能发生。 这属于“任何东西”的标题,所以它可能发生。
至于为什么编译器没有注意到你的错误:你可能忽略了在头文件中声明覆盖,所以它假设你的方法与它能找到的最近的声明NSObject的签名相同。
听Chuck。 他很聪明:)
我会尝试添加更多细节。
考虑这一点的一种方法是“如果两者都被声明-(id)init
,A将如何将其值返回给B”?
它就是这样的。 return self
声明将指针指向A并将其放在商定的位置。 该位置将在ABI中定义。 在OSX / x86-64机器上,它是RAX寄存器(IIRC)。 所以return self
真的说“将自我指针写入RAX”。
然后,当B重新获得控制权时,它知道返回值是在RAX中,并且可以随意使用它。 请注意,您没有从A的实现中删除return self
声明,因此self可能仍然写入RAX,其中B找到并使用它。 或者也许RAX仍然有来自NSObject init
实现的指针。 你必须拆卸它才能确定。
现在让我们假设你没有在A的实现中保留return self
。 现在在RAX中有一些随机垃圾,B会尝试使用它,因为它是指向A的指针。这是Chuck提到的未定义行为的地方。如果你很幸运它会崩溃。
我猜你上面的代码给了一些编译器错误/警告你必须压制?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.