为什么编译器在 [NSObject init] 上没有 return 错误
Why compiler doesn't return error on [NSObject init]
当我尝试编译以下代码时:
int main(int argc, const char * argv[])
{
@autoreleasepool {
[NSObject init];
}
return 0;
}
编译器让它构建,然后应用程序在运行时崩溃,出现以下异常:
2017-08-14 14:56:07.937859-0700 NSObjectInit[30512:11241814] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSObject<0x7fff9fd83140> init]: cannot init a class object.'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff818e32cb __exceptionPreprocess + 171
1 libobjc.A.dylib 0x00007fff966f348d objc_exception_throw + 48
2 CoreFoundation 0x00007fff8196517f +[NSObject(NSObject) init] + 127
3 NSObjectInit 0x0000000100000f2d main + 61
4 libdyld.dylib 0x00007fff96fd9235 start + 1
5 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
据我了解,NSObject class中有+init方法,但我在public headers中没有找到它,如果它是私有的,编译器应该告诉我们没有这样的方法。知道为什么编译器让我们构建这段代码吗?
类本身就是对象。每个 class 都有一个隐含的 "meta-class",而 class 是该元 class 的唯一实例。我们通常认为的 "class method on class Foo" 也是 class meta-Foo 上的实例方法。
还有一个怪癖,class 层次结构的根 class 的元 class 是根 class 的子class本身。即meta-NSObject
继承自NSObject
。 class NSObject
是它自己的一个实例!
因此,NSObject
的任何实例方法也是 NSObject
的 class 方法。也就是说,它可以在 NSObject
class 本身上调用。这就是编译器对 [NSObject init]
.
没有问题的原因
http://sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html
正如 Ken Thomases 所说,此行为与 NSObject 的 meta-class 有关。简而言之,我们可以在 class 实例的 class 上调用 NSObject 的所有方法。
For all instances, classes and meta-classes in the NSObject hierarchy,
this means that all NSObject instance methods are valid. For the
classes and meta-classes, all NSObject class methods are also valid.
当我尝试编译以下代码时:
int main(int argc, const char * argv[])
{
@autoreleasepool {
[NSObject init];
}
return 0;
}
编译器让它构建,然后应用程序在运行时崩溃,出现以下异常:
2017-08-14 14:56:07.937859-0700 NSObjectInit[30512:11241814] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSObject<0x7fff9fd83140> init]: cannot init a class object.'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff818e32cb __exceptionPreprocess + 171
1 libobjc.A.dylib 0x00007fff966f348d objc_exception_throw + 48
2 CoreFoundation 0x00007fff8196517f +[NSObject(NSObject) init] + 127
3 NSObjectInit 0x0000000100000f2d main + 61
4 libdyld.dylib 0x00007fff96fd9235 start + 1
5 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
据我了解,NSObject class中有+init方法,但我在public headers中没有找到它,如果它是私有的,编译器应该告诉我们没有这样的方法。知道为什么编译器让我们构建这段代码吗?
类本身就是对象。每个 class 都有一个隐含的 "meta-class",而 class 是该元 class 的唯一实例。我们通常认为的 "class method on class Foo" 也是 class meta-Foo 上的实例方法。
还有一个怪癖,class 层次结构的根 class 的元 class 是根 class 的子class本身。即meta-NSObject
继承自NSObject
。 class NSObject
是它自己的一个实例!
因此,NSObject
的任何实例方法也是 NSObject
的 class 方法。也就是说,它可以在 NSObject
class 本身上调用。这就是编译器对 [NSObject init]
.
http://sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html
正如 Ken Thomases 所说,此行为与 NSObject 的 meta-class 有关。简而言之,我们可以在 class 实例的 class 上调用 NSObject 的所有方法。
For all instances, classes and meta-classes in the NSObject hierarchy, this means that all NSObject instance methods are valid. For the classes and meta-classes, all NSObject class methods are also valid.