设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

从 C++ 到 Objective-C 的快速指南

2014-5-15 09:41| 发布者: 红黑魂| 查看: 4007| 评论: 0|来自: 开源中国编译

摘要: 简介当我开始为iOS写代码的时候,我意识到,作为一个C++开发者,我必须花费更多的时间来弄清楚Objective-C中怪异的东西。这就是一个帮助C++专家的快速指南,能够使他们快速的掌握Apple的iOS语言。请注意这绝不是一个 ...

数组

1// Objective-C
2NSArray* a1 = [NSArray alloc] initWithObjects: @"hello",@"there",nil];
3NSString* first = [a1 objectAtIndex:0];

NSArray和NSMutableArray是在Objective-C中处理数组的 两个类(两者的差异是,NSArray元素构造时必须通过构造函数,而NSMutableArray可以在之后更改)。典型构造函数的生效,你必须通过nil去作为“结尾元素”。排序/搜索/插入函数对于NSArray和NSMutableArray来说是一样的,在第一行中的例子它返回一个新的NSArray,而在NSMutableArray的例子里,它修改的是一个存在的对象。

分类

01// C++
02class MyString : public string
03{
04public:
05  void printmystring() { printf("%s",c_str()); }
06};
07 
08 
09// Objective-C
10@interface MyString (NSString)
11- (void) printmystring;
12@end
13 
14@implementation MyString (NSString)
15- (void) printmystring
16{
17 printf("%@",self);
18}
19@end
20 
21// C++
22MyString s1 = "hi";
23s1.printmystring(); // ok
24string s2 = "hello";
25s2.printmystring(); // error, we must change s2 from string to MyString
26 
27// Objective-C
28NSString* s2 = @"hello";
29[s2 printmystring]; // valid. We extended NSString without changing types.

C++依赖 继承机制来实现一个已知的类。这是很麻烦的,因为所有用户的实现类必须使用另外的类型名称(在例子中,MyString用来代替string)。Object-C通过使用 分类(Categories)允许扩展一个已知的类内 同型(same type。上面链接中所有源代码在extension.h文件 (具有代表性的是像NSString+MyString.h这样的)中可以查看,上面例子中,我们立即就有可以调用新的成员函数,而不需要改变NSString类型为MyString。


块 和 Lambda

1// Objective-C
2// member function
3-(void)addButtonWithTitle:(NSString*)title block:(void(^)(AlertView*, NSInteger))block;
4 
5// call
6[object addButtonWithTitle:@"hello" block:[^(AlertView* a, NSInteger i){/*DO SOMETHING*/}];

块 是Objective-C 用来模拟lambda功能的一种方式. 查看Apple的文档,从AlertView的示例 (使用块的UIAlertView)可以获得更多有关块的技术.

C++ 开发者使用 Objective-C 和 ARC 的重要提示

01// C++
02class A
03{
04public:
05 
06   NSObject* s;
07   A();
08};     
09 
10A :: A()
11 {
12 s = 0// 可能会奔溃,这是常发生在发布模式下!
13 }

你已经知道给所有的顾客都打两折对你而言有多痛苦了,因为你bug重重的软件会在发布模式下奔溃,而在调试模式下总是妥妥的. 没有用户会理解程序员,是不是?

让我们来看看这里发生了什么.  s = 0 这一行将 0 赋值给了一个变量,而因此不管这个变量之前取值是什么,首先都会被释放掉,所以编译器在赋值之前执行了一次 [s release] . 如果 s 之前已经是 0 了,假设是在调试构建的话,不会发生任何不好的事情; 如果 s 是一个nil的话,使用[s release] 是再好也不过的. 然而,在发布模式下, s可能是一个野指针,所以它可能在被“初始化”为0之前包含任何值(这很危险是不是?).


在C++中,这并不是一个问题,因为它里面是不存在ARC的. 而在Objective-C中编译器并没有办法了解这是一次"赋值" 还是一次 "初始化" (如果是后者,它就不会发送发布消息).

下面是正确的方式:

01// C++
02class A
03{
04public:
05 
06   NSObject* s;
07   A();
08};     
09 
10A :: A() :s(0// 现在编译器就知道确定 it's 是一次初始化了, 一次就不存在 [s release]
11 {
12 }

现在编译器就不会去尝试调用一个 [s release] 因为它知道它是这个对象的第一次初始化. 请小心!

从Objective-C 对象到 C++ 类型的转换

1// Objective-C
2NSObject* a = ...;
3void* b = (__bridge void*)a; // 你必须在Objective-C和C类型支架使用 __bridge 
4void* c = (__bridge_retained void*)a; // 现在是一个+1的保留计数,而你必须在稍后释放这个对象
5NSObject* d = (__bridge_transfer NSObject*)c; // 现在ARC取得了对象c的”拥有权“, 将其装换成一个ARC管理的NSObject.

我可以分析这一切,而我的建议是简单的. 不要 将ARC类型和非ARC类型混在一起. 如果你必须转换一些Objective-C对象的话,使用id而不是void*. 否则,你将会遇到严重的内存故障.


Objective-C 有而 C++ 没有的

  • 分类Categories

  • 基于NSObject的操作

  • YES 和 NO (等价于true和false)

  • NIL 和 nil (等价于0)

  • 可命名的函数参数

  • self (等价于 this) 而其可以在一个构造器中被改变

C++ 有而 Objective-C 没有的

  • 静态对象. Objective-C 中的对象不能被初始化成静态的,或者是存在于栈中. 只能是指针.

  • 多重继承

  • 命名空间

  • 模板

  • 操作符重载

  • STL 和算法 ;

  • 方法可以是受保护的( protected )或者私有的( private ) (在Obj-C中,只能是公共的)

  • const/mutable 项

  • friend 方法

  • 引用

  • 匿名函数签名 (没有变量名称)

阅读更多
从C++ 到 Objective-C 指南, 这里.

历史记录

  • 10/05/2014 : 第一次发布.



参与翻译(4人)


本文地址:http://www.oschina.net/translate/from-cplusplus-to-objective-c-a-quick-guide

酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部