繁体   English   中英

Objective C init方法和继承

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM