从 C++ 到 ObjectiveC 的快速指南.docx
《从 C++ 到 ObjectiveC 的快速指南.docx》由会员分享,可在线阅读,更多相关《从 C++ 到 ObjectiveC 的快速指南.docx(15页珍藏版)》请在冰豆网上搜索。
从C++到ObjectiveC的快速指南
从C++到Objective-C的快速指南
当我开始为iOS写代码的时候,我意识到,作为一个C++开发者,我必须花费更多的时间来弄清楚Objective-C中怪异的东西。
这就是一个帮助C++专家的快速指南,能够使他们快速的掌握Apple的iOS语言。
请注意这绝不是一个完整的指南,但是它让你避免了阅读100页的手册。
除此之外,我知道你喜欢我的写作风格。
背景
需要C++的技能,我会比较C++和Objective-C的东西。
此外,COM编程也是有用的,因为Objective-C有类似于IUnkown的东西,因此基础的COM编程是有帮助的(但不是必须的)
ObjectiveC++是C++和ObjectiveC的组合。
你也能使用任何C++的东西混合到ObjectiveC中,但是记住重新命名你的文件从.m到.mm
铛-铛!
我们马上就开始我们的教程.首先我会介绍Objective-C的东西,然后是C++中与它对等的东西.
成员函数
1.// Objective-C
2.- (int) foo :
(int) a :
(char) b {}
3.+ (int) foo :
(int) a :
(char) b {}
4.
5.// C++
6.int foo(int a,char b) {}
7.static int foo(int a,char b) {}
8.
9.// Objective-C
10.- (void) foo2 val1:
(int) a; // named argument
11.// auto; height:
auto; float:
none;"> none;">#0000ff;font-size:
14px;width:
auto;height:
auto;float:
none;">call
12.[obj foo2 val1:
5]; // merely helper:
You remember that 5 is assigned to param name val1.
-表示的是一个一般的成员函数(通过一个对象实体访问),而+则表示一个静态成员函数,不需要使用实体就能访问.当然,像C++,静态成员不能访问实体变量.
此外,Objective-C函数函数可以有赋予了名称的参数,这样让什么参数获得什么值会更一目了然.理论上,被赋予了名称的参数允许程序员按任何顺序传入参数,但是Objective-C却规定要按声明的顺序传参.
通过一个指针或者一个静态成员调用一个成员
1.// Objective-C
2.NSObject* ptr = ...; // some pointer
3.[ptr foo:
5:
3]; // auto; height:
auto; float:
none;"> none;">#0000ff;font-size:
14px;width:
auto;height:
auto;float:
none;">call
foo member with arguments 5 and 3
4.[NSObject staticfoo:
5:
3]; // call static function of NSOBject with arguments 4 and 3
5.
6.// C++
7.CPPObject* ptr = ...; // some pointer
8.ptr->foo(5,3);
9.CPPObject:
:
staticfoo(5,3);
Objective-C使用[]来调用成员函数并传入用:
分割开的参数,其对于ObjectiveC中ptr为nil的情况非常友好,在这种情况下“调用”将会被忽略掉(而在C++中,这种情况会抛出一个指针冲突异常).这使得消除对nil对象的检查成为可能.
协议VS接口
1.// Objective-C
2.@protocol foo
3.- (void) somefunction;
4.@end
5.
6.@interface c1 :
NSObject
7.
8.@end
9.
10.@implementation c1
11.- (void) somefunction { ... }
12.@end
13.
14.// C++
15.class foo
16.{
17.virtual void somefunction() = 0;
18.};
19.
20.class c1 :
public NSObject, public foo
21.{
22.void somefunction() { ... }
23.}
协议=抽象类.Objective-C和C++之间的区别在于,在Objective-C中,函数并不是必须要被实现的.你可以让一个可选的方法被动的被声明,而这仅仅只是向编译器发出暗示而已,并不是编译必须的.检查一个方法是否被实现了
1./ Objective-C
2.NSObject* ptr = ...; // some pointer
3.[ptr somefunction:
5:
3]; // NSObject 不必一定为其编译而实现somefunction. 如果没有被实现的话,会引发异常.
4.
5.// C++
6.CPPObject* ptr = ...; // some pointer
7.ptr->somefunction(5,3); // CPPObject 必须实现 somefunction() 否则程序根本就不会被编译.
Objective-C成员函数就是(Smalltalk中的)"消息"而在Objective-C中时,我们则说接收者(即指针)会向一个选择器做出回应,这意味着其实现了我们尝试去调用的虚函数.当有一个接口是,C++对象必须实现其所有的成员函数.而在Objective-C中这并不是必须的,因此我们可以向并不必须要实现它的某个地方发送一个”消息“(如此就会引发一个异常).
//Objective-C
NSObject*ptr=...;//somepointer
if([ptrrespondsToSelector:
@selector(somefunction:
:
)]
[ptrsomefunction:
5:
3];
现在我们就可以确定接收者向选择器做出回应,我们因此就可以调用它了.在C++中不需要这样的检查,因为实现必须常常”向选择器做出回应“,否则源代码根本就不会被编译.请注意我们必须知道选择器获取了多少个参数(因此在该@selector中是2个:
:
s
向下转型
1.// Objective-C
2.NSObject* ptr = ...; // some pointer
3.if ([ptr isKindOfClass:
[foo class]]
4.[ptr somefunction:
5:
3];
5.
6.// C++
7.CPPObject* ptr = ...; // some pointer
8.foo* f = dynamic_cast(ptr);
9.if (f)
10.f->somefunction(5,3);
现在只有使用NSObject的"isKindOfClass"助手——所有Object-C类的基础,才能像在C++中那样向下转型.
符合协议?
1.// Objective-C
2.NSObject* ptr = ...; // some pointer
3.if ([ptr conformsToProtocol:
@protocol(foo)]
4.[ptr somefunction:
5:
3];
5.
6.// C++
7.CPPObject* ptr = ...; // 某个也继承自foo的指针
8.foo* f = ptr; // 或者 auto; height:
auto; float:
none;"> none;">#0000ff;font-size:
14px;width:
auto;height:
auto;float:
none;">编译器
会警告我们说ptr不能同foo兼容.
9.f->somefunction(5,3);
现在我们要检查接收器是否符合一个协议(或者说,在C++就是实现一个接口),以便我们可以发送这个协议包含的消息.嘿嘿,它像极了Java的类和接口,而在C++中,完全被实现的类和一个“接口”之间没有技术上的差别.
1.void* 、 id 或者 SEL?
2.
3.// Objective-C
4.id ptr = ...; // some pointer
5.if ([ptr conformsToProtocol:
@protocol(foo)]
6.[ptr somefunction:
5:
3];
7.SEL s = @selector(foo:
); // a pointer to a function foo that takes 1 parameter
8.
9.// C++
10.void* ptr = ...; // some pointer
11.foo* f = dynamic_cast(ptr);
12.if (f)
13.f->somefunction(5,3);
id是通用的用于Objective-C类的类似于void*的东西.你只能使用id而不是void*因为id可以通过ARC(稍后会详细介绍到它)编程一个可被管理的指针,而因此编译器需要在元指针类型和Objective-C指针之间做出区分.SEL是一个用于选择器(C++函数指针)的通用类型,而你一般可以通过使用关键字@selector带上函数名字和:
:
:
:
:
s的一个数字来创建一个选择器,这取决于可以传入多少参数.选择器实际上就是一个字符串,它会在运行时绑定到一个方法识别器.
类定义,方法,数据,继承
1.// Objective C
2.@class f2; // forward declaration
3.@interface f1 :
NSOBject // Objective-C supports only public and single inheritance
4.{
5.int test; // default = protected
6.@public
7.int a;
8.int b;
9.f2* f;
10.}
11.- (void) foo;
12.@end
13.
14.@implementation f1
15.- (void) foo
16.{
17.a = 5; // ok
18.self->a = 5; // ok
19.super.foo(); // parent auto; height:
auto; float:
none;"> none;">#0000ff;font-size:
14px;width:
auto;height:
auto;float:
none;">call
20.}
21.@end
22.
23.// C++
24.class f1 :
public CPPObject
25.{
26.int test; // default = private
27.public:
28.class f2* f; // forward declaration
29.int a;
30.int b;
31.void foo();
32.}
33.
34.void f1 :
:
foo()
35.{
36.a = 5; // ok
37.this->a = 5; // ok
38.CPPOBject:
:
foo(); // parent call
39.}
Objective-C中的实现范围在@implementation/@end标记(在C++中我们可以将实现放在任何带有:
:
范围操作符的地方)之中.它使用@class关键字用于事先声明.Objective-C默认带有私有(private)保护,但仅用于数据成员(方法必须是公共的).Objective-C使用self而不是this,并且它还可以通过super关键字调用它的父类.
构造器和析构器
1.// Objective-C
2.NSObject* s = [NSObject alloc] init]; // can return nil if construction failed
3.[s retain]; // Increment the ref count
4.
5.// C++
6.CPPObject* ptr = new CPPObject(); // can throw
7.ptr->AddRef();
8.
9.// Objective-C
10.NSObject* s = [NSObject alloc] initwitharg:
4];
11.[s release];
12.
13.// C++
14.CPPOBject* ptr = new CPPOBject(4);
15.ptr->Release();
Objective-C中的内存分配是通过静态成员方法alloc来实现的,所有(做为NSObject后裔)的对象都有这个方法.self在Objective-C中是可以被赋值的,而如果构建失败的话它就会设置成nil(而在C++中则会被抛出一个异常).内存分配之后实际被构造器调用的是一个公共的成员函数,在Objective-C中默认的是init方法.
Objective-C使用同COM益阳的引用计数方法,而它也使用retain和release(等同于IUnknown的AddRef()和Release()方法).当引用计数到了0,则对象会从内存中被移除掉.
多线程
1.// Objective C
2.@interface f1 :
NSOBject // Objective-C supports only public and single inheritance
3.{
4.}
5.- (void) foo;
6.- (void) threadfunc :
(NSInteger*) param;
7.- (void) mt;
8.
9.@end
10.
11.@implementation f1
12.
13.- (void) threadfunc :
(NSInteger*) param
14.{
15.[self performSelectorOnMainThread:
@selector(mt)];
16.}
17.
18.- (void) mt
19.{
20.}
21.
22.- (void) foo
23.{
24.[self performSelectorInBackground:
@selector(thradfunc:
) withObject:
1 waitUntilDone:
false];
25.
}
26.@end
Objective-C 有一些针对NSObject的内建功能,可以在另外一个线程中操作一个选择器(==调用一个成员),在主线程中,等待一次调用等等.在NSObject参见更多信息.
内存和ARC
1.// Objective-C
2.@interface f1 :
NSObject
3.{
4.}
5.@property (weak) NSAnotherObject* f2; // 当没有其它强引用存在的时候,它将会被自动设置成
@end
-(void)foo
{
NSObject*s=[NSObjectalloc] init];//如果构造失败的话会返回nil
//uses
//end.Hooraah!
Compilerwillautomatiauto;height:
auto;float:
none;">none;">#0000ff;font-size:
14px;width:
auto;height:
auto;float:
none;">callycall[srelease]forus!
}
这里需要你忘记自己良好的C++习惯.OKObjective-C使用了一个垃圾收集机制,这种东西我们C++很讨厌,因为它很慢并会让我们想到Java.但是ARC(自动进行引用计算)是一种编译时间特性,它会告诉编译器"这里是我的对象:
请帮我算算啥时候它们才要被销毁吧".使用ARC你就不需要发送retain/release消息给你的对象了;编译器会自动帮你代劳的.
为了能帮助编译器决定保留一个对象多长时间,你还要一个弱引用指向一个变量.默认的,所有的变量都是强引用(==只要强引用还存在,被引用的对象就会存在下去).你也可以获取一个弱引用,它会随着每个强引用消失而失去它的值.这在类成员从XCode的BuilderInterface(像RC编辑器)处获取它们的值时,会很有用,当类被销毁时,那些成员也会失去它们的值.
Strings
1.//