从c++到objective-c快速扫盲
本来选的网络方向,坑爹的老师居然把我们劈出去做.net项目。
于是对.net深恶痛绝的某人费了九牛二虎之力终于跳到了嵌入式项目组。。。
哎,之前没听过嵌入式的课,于是只好最快的速度读完了《from c++ to objective-c》和《objc runtime guide》。其实objective-c并没有网上传闻的那么变态。接下来就以一个c++程序员的角度,来总结下我学习objective-c中遇到的问题吧。
由于我接触objective-c的时间也不长(不到一周),所以总结中多有纰漏,还望各位大虾指正。
阅读本文章需要:c++基础。
扫盲一:objective-c是什么?
负责任的告诉你,objective-c和c++的历史沿革一样长。都是给c语言包装了一下,使他具有了面向对象的功能。也就是说objective-c是一门面向对象的语言。
扫盲二:objective-c和c++的不同是什么?
在这里我不想说什么objective-c只有单继承什么的,这些都是屁话。
我要说的是,c++是静态语言,objective-c是个动态语言。
有一定c++基础的人都知道,c++编译器会对c++进行处理,类处理为结构体和“悬挂在外”的函数,方法的调用会处理为“经过名字分解”的函数调用,虚函数会处理为在虚函数表中的偏移量。这些都是用静态的方法来模拟动态的处理(动态类型识别,多态)。
objective-c有个runtime,在apple的所有系统下运行,编译完的代码都会经过这个runtime去处理。
比如常见的[receiver message]会被编译器处理为
objc_msgSend(receiver, selector, arg1, arg2, ...)
如果参数错了,函数会在编译时报错吗?不会,这就是为什么传递一个错误的消息不会产生编译时错误,而是运行时错误。
为什么是运行时错误呢?objective-c里,每一个类都会包含如下两个信息“a pointer to the superclass”和“a class dispatch table”。没错,runtime就是在dispatch table里找到消息和方法的对应关系,然后去调用的。如果本类中没有找到可以调用的方法,则通过superclass去父类查看。
于是,在objective-c里就有了很多动态的方法:比如动态添加类,动态添加方法的实现等等。。
扫盲三:cocoa是什么?
依旧很负责任的告诉你,如果没有cocoa,objective-c照样可以活着,不是只有继承自NSObject的类才叫类。事实上,所有的类都是结构体,感兴趣的可以去Xcode里go to definition。或者去网上淘GCC源代码。
cocoa是一组类,可以方便程序员的使用。
扫盲四:self是什么,super是什么?
self是一个id类型的变量,super是一个标志。
通过self类型你可以想本类对象发送消息,super的目的是告诉编译器,你要从self的父类里去寻找相应的方法,而接受消息的实体依旧是self,没看懂的请移步“扫盲二”。
扫盲五:alloc是什么,init是什么?
alloc是分配内存,init是调用构造函数。
不知道大家有没有在这个问题上卡到过:
if (self = [super init])
呀!self被复制为父类对象的指针了,怎么办?父类对象的空间会不会不够啊?objective-c难道做了什么特殊处理了吗?
如果你没有被卡到,要么你认真的读过了obc的手册,否则就是个不怎么喜欢思考的人。
别忘了!初始化一个类分为两步[[classname alloc] init]
第一步是分配空间,而super的目的,“扫盲四”里说了,接受消息的依然是子类!他不是父类。
扫盲六:retain和release
retain使引用计数加一,release相反。
autorelease将该对象注册到NSAutoreleasePool里面。
NSAutoreleasePool组织形式是个栈,也就是最后生成的autoreleasePool放在栈顶,新注册对象将放到栈顶的释放池里。这就是文档中所说的“When an object receives autorelease,it knows how to find the closest autoreleasepool.”
临时就想到了这些,如果大家有什么更正,或者更好的解释,或者自己学习中也有问题想要分享,不妨拿出来讨论。有讨论才有进步。学生再次谢过诸位了。