简介当我开始为iOS写代码的时候,我意识到,作为一个C++开发者,我必须花费更多的时间来弄清楚Objective-C中怪异的东西。这就是一个帮助C++专家的快速指南,能够使他们快速的掌握Apple的iOS语言。 请注意这绝不是一个完整的指南,但是它让你避免了阅读100页的手册。除此之外,我知道你喜欢我的写作风格。 背景需要C++的技能,我会比较C++和Objective-C的东西。此外,COM编程也是有用的,因为Objective-C有类似于IUnkown的东西,因此基础的COM编程是有帮助的(但不是必须的) Objective C++是C++和Objective C的组合。你也能使用任何C++的东西混合到Objective C中,但是记住重新命名你的文件从.m到.mm
铛 - 铛!我们马上就开始我们的教程. 首先我会介绍 Objective-C 的东西,然后是C++中与它对等的东西. 成员函数 02 | - ( int ) foo : ( int ) a : ( char ) b {} |
03 | + ( int ) foo : ( int ) a : ( char ) b {} |
06 | int foo( int a, char b) {} |
07 | static int foo( int a, char b) {} |
10 | - ( void ) foo2 val1:( int ) a; |
- 表示的是一个一般的成员函数(通过一个对象实体访问), 而 + 则表示一个静态成员函数, 不需要使用实体就能访问. 当然,像C++, 静态成员不能访问实体变量. 此外,Objective-C函数函数可以有赋予了名称的参数,这样让什么参数获得什么值会更一目了然. 理论上,被赋予了名称的参数允许程序员按任何顺序传入参数,但是Objective-C却规定要按声明的顺序传参. 通过一个指针或者一个静态成员调用一个成员 4 | [NSObject staticfoo: 5 : 3 ]; |
9 | CPPObject::staticfoo( 5 , 3 ); |
Objective-C 使用 [ ] 来调用成员函数并传入用:分割开的参数, 其对于ObjectiveC中ptr为nil的情况非常友好,在这种情况下“调用”将会被忽略掉(而在C++中,这种情况会抛出一个指针冲突异常 ). 这使得消除对nil对象的检查成为可能.
协议VS接口 06 | @interface c1 : NSObject<foo> |
11 | - ( void ) somefunction { ... } |
17 | virtual void somefunction() = 0 ; |
20 | class c1 : public NSObject, public foo |
22 | void somefunction() { ... } |
协议= 抽象类. Objective-C 和 C++ 之间的区别在于,在 Objective-C 中, 函数并不是必须要被实现的. 你可以让一个可选的方法被动的被声明,而这仅仅只是向编译器发出暗示而已,并不是编译必须的. 检查一个方法是否被实现了 Objective-C 成员函数就是(Smalltalk中的) "消息" 而在Objective-C中时,我们则说接收者 (即指针) 会向一个选择器做出回应, 这意味着其实现了我们尝试去调用的虚函数. 当有一个接口是, C++ 对象必须实现其所有的成员函数. 而在 Objective-C 中这并不是必须的,因此我们可以向并不必须要实现它的某个地方发送一个”消息“ (如此就会引发一个异常). 3 | if ([ptr respondsToSelector: @selector (somefunction::)] |
4 | [ptr somefunction: 5 : 3 ]; |
现在我们就可以确定接收者向选择器做出回应, 我们因此就可以调用它了. 在 C++ 中不需要这样的检查, 因为实现必须常常”向选择器做出回应“, 否则源代码根本就不会被编译. 请注意我们必须知道选择器获取了多少个参数(因此在该@selector中是2个 ::s
向下转型
03 | if ([ptr isKindOfClass:[foo class ]] |
04 | [ptr somefunction: 5 : 3 ]; |
08 | foo* f = dynamic_cast<foo*>(ptr); |
现在只有使用NSObject的"isKindOfClass"助手——所有Object-C类的基础,才能像在C++中那样向下转型.
符合协议? 3 | if ([ptr conformsToProtocol: @protocol (foo)] |
4 | [ptr somefunction: 5 : 3 ]; |
现在我们要检查接收器是否 符合一个协议 (或者说,在C++就是实现一个接口), 以便我们可以发送这个协议包含的消息. 嘿嘿,它像极了Java的类和接口,而在C++中,完全被实现的类和一个“接口”之间没有技术上的差别. void* 、 id 或者 SEL? 03 | if ([ptr conformsToProtocol: @protocol (foo)] |
04 | [ptr somefunction: 5 : 3 ]; |
05 | SEL s = @selector (foo:); |
09 | foo* f = dynamic_cast<foo*>(ptr); |
id 是通用的用于Objective-C类的类似于 void* 的东西. 你只能使用id而不是 void* 因为id可以通过ARC(稍后会详细介绍到它)编程一个可被管理的指针,而因此编译器需要在元指针类型和Objective-C指针之间做出区分. SEL 是一个用于选择器(C++函数指针)的通用类型,而你一般可以通过使用关键字@selector带上函数名字和:::::s的一个数字来创建一个选择器, 这取决于可以传入多少参数. 选择器实际上就是一个字符串,它会在运行时绑定到一个方法识别器.
|