从 C++ 到 Objective-C(18):字符串和 C++ 特性

字符串

Objective-C 中唯一的 static 对象

在 C 语言中,字符串就是字符数组,使用char *指针。处理这种数据非常困难,并且可能引起很多 bug。C++ 的string类是一种解脱。在 Objective-C 中,前面我们曾经介绍过,所有对象都不是自动的,都要在运行时分配内存。唯一不符合的就是 static 字符串。这导致可以使用 static 的 C 字符串作为NSString的参数。不过这并不是一个好的主意,可能会引起内存浪费。幸运的是,我们也有 static 的 Objective-C 字符串。在使用引号标记的 C 字符串前面加上 @ 符号,就构成了 static 的 Objective-C 字符串。

NSString* notHandy = [[NSString alloc] initWithUTF8String:"helloWorld"];
NSString* stillNotHandy = // initWithFormat 类似 sprintf()
                          [[NSString alloc] initWithFormat:@"%s", "helloWorld"];
NSString* handy = @"hello world";

另外,static 字符串可以同普通对象一样作为参数使用。

int size = [@"hello" length];
NSString* uppercaseHello = [@"hello" uppercaseString];

NSString 和编码

NSString对象非常有用,因为它增加了很多好用的方法,并且支持不同的编码,如 ASCII、UNICODE、ISO Latin 1 等。因此,翻译和本地化应用程序也变得很简单。

对象描述,%@扩展,NSString转 C 字符串

在 Java 中,每一个对象都继承自Object,因此都有一个toString()方法,用于使用字符串形式描述对象本身。这种功能对于调试非常有用。Objective-C 中,类似的方法叫做description(),返回一个NSString对象。

C 语言的printf()函数不能输出NSString。我们可以使用NSLog获得类似的功能。NSLog类似于printf(),可以向控制台输出格式化字符串。需要注意的是,NSString的格式化符号是 %@,不是 %s。事实上,%@ 可以用于任意对象,因为它实际是调用的-(NSString*) description

NSString可以使用UTF8String方法转换成 C 风格字符串。

char* name = "Spot";
NSString* action1 = @"running";
printf("My name is %s, I like %s, and %s...\n",
    name, [action1 UTF8String], [@"running again" UTF8String]);
NSLog(@"My name is %s, I like %@ and %@\n",
    name, action1, @"running again");

C++ 特性

现在,你已经了解到 C++ 的面向对象概念在 Objective-C 中的描述。但是,另外一些 C++ 的概念并没有涉及。这些概念并不相关面向对象,而是关于一些代码编写的问题。

引用

Objective-C 中不存在引用(&)的概念。由于 Objective-C 使用引用计数器和 autorelease 管理内存,这使得引用没有多大用处。既然对象都是动态分配的,它们唯一的引用就是指针。

内联

Objective-C 不支持内联 inline。对于方法而言,这是合理的,因为 Objective-C 的动态性使得“冻结”某些代码变得很困难。但是,内联对某些用 C 编写的函数,比如 max(), min() 还是比较有用的。这一问题在 Objective-C++ (这是另外一种类似的语言)中得到解决。

无论如何,GCC 编译器还是提供了一个非标准关键字__inline或者__inline__,允许在 C 或者 Objective-C 中使用内联。另外,GCC 也可以编译 C99 代码,在 C99 中,同样提供了内联关键字inline(这下就是标准的了)。因此,在基于 C99 的 Objective-C 代码中是可以使用内联的。如果不是为了使用而使用内联,而是关心性能,那么你应该考虑 IMP 缓存。

模板

模板是独立于继承和虚函数的另外一种机制,主要为性能设计,已经超出了纯粹的面向对象模型(你注意到使用模板可以很巧妙的访问到 private 变量吗?)。Objective-C 不支持模板,因为其独特的方法名规则和选择器使得模板很难实现。

运算符重载

Objective-C 不支持运算符重载。

友元

Objective-C 没有友元的概念。事实上,在 C++ 中,友元很大程度上是为了实现运算符重载。Java 中包的概念在一定程度上类似友元,这可以使用分类来处理。

const 方法

Objective-C 中方法不能用 const 修饰。因此也就不存在 mutable 关键字。

初始化列表

Objective-C 中没有初始化列表的概念。

Leave a Reply