Vse*_*lny 3 oop iphone objective-c ios
我有2个A和B类,B继承自A,A继承自NSObject.Class A有一个函数 - (void)init:
- (void)init {
if (self = [super init]) {
NSLog(@"A");
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
B有:
- (id)init {
if (self = [super init]) {
NSLog(@"B");
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
编译后我在我的控制台中有"A"和"B",尽管B中的条件"if(self = [super init])"不能为真,导致其超类init方法返回void.任何想法?
PS我知道init方法必须返回id,我很感兴趣,为什么这样做有效,而不应该.
您通过分配void函数调用的结果来调用未定义的行为.未定义的行为意味着几乎任何事情都可能发生.这属于"任何东西"的标题,所以它可能发生.
至于为什么编译器没有注意到你的错误:你可能忽略了在头文件中声明覆盖,所以它假设你的方法与它能找到的最近的声明NSObject的签名相同.
听Chuck.他很聪明:)
我会尝试添加更多细节.
考虑这一点的一种方法是"如果两者都被宣布-(id)init将如何将其值返回给B"?
它就是这样的.该return self语句将指针指向A并将其放在商定的位置.该位置将在ABI中定义.在OSX/x86-64机器上,它是RAX寄存器(IIRC).所以return self真的说"将自己的指针写入RAX".
然后,当B重新获得控制权时,它知道返回值是在RAX中,并且可以随意使用它.请注意,您没有return self从A的实现中删除该语句,因此self可能仍然写入RAX,其中B找到并使用它.或者也许RAX仍然有来自NSObject init实现的指针.你必须拆卸它才能确定.
现在让我们说你没有保留return selfA的实现.现在在RAX中有一些随机垃圾,B会尝试使用它,因为它是指向A的指针.这是Chuck提到的未定义行为的地方.如果你很幸运它会崩溃.
我猜你上面的代码给了一些编译器错误/警告你必须压制?
| 归档时间: |
|
| 查看次数: |
846 次 |
| 最近记录: |