这一条的要点最后再总结吧。
先说说#define,当我们在代码中要定义一个常量的时候,我们可能会使用下面这种方式:
#define whatEver 100
这样的预处理指令会把代码中的相关定义内容全部替换成100,达到了我们想要的效果。
那么还有没有更好的方式呢?
我们可以使用这样的方式:
static const int whatEver 100;
这样写的好处:
1.当我们在使用#define的时候,是没有任何类型信息的。第二种方式则有类型信息,有助于阅读和编写代码。
2.如果使用了预处理指令,即使有人重新定义了常量值,编译器也不会产生警告。
在哪里写?
如果我们在头文件位置声明了一条#define预处理命令,那么所有引入该头文件的代码中的如果碰巧有相关内容,都会被替换,可能会造成意想不到的后果。
定义类型常量也是如此。
如果不需要公开
如果要定义一个不需要对外公开的常量,我们只需要在使用该常量的实现文件中定义即可。
//classA.m文件中
#import "classA.h"
@interface classA()
//...
@end
static const int whatEver = 100;
@implementation classA
//...
@end
const修饰了该变量保证其不会被修改。static修饰了该全局变量,使其作用域为当前文件内。
如果需要公开
如果需要公开的话,比如分发通知时的通知名称,此时我们可以这样:
//.h文件中声明
extern NSString* const whatEver;
//.m中实现
NSString* const whatEver = @"NAME";//注意没有static修饰符
extern这个关键字告诉编译器,连接成二进制文件时一定能找到这个常量,所以无需查看其定义可以允许直接使用。
这里有一个小思考(不知正误),为什么const在修饰NSString的时候放在了*和变量名之间。
在C/C++中我们知道const修饰指针的时候可以放在这两个位置:
int a = 1; //第0行
const int * p = &a;//第1行
int * const p = &a;//第2行
第一行表示 无法通过p这个指针修改其指向的变量,但是可以修改p指针指向别的地方。
第二行表示 无法修改p指针指向别的地方,但是可以通过p指针修改其指向的变量。
那么 NSString* const whatEver = @"NAME"; 这样的方式保证了指针不会指向别的地方,那么为什么没有在前面再加一个const保证内容不会被改变呢?
这又要从C/C++说起了,
char * str = "hello";
在C/C++中,使用字符串初始化一个char*指针,默认就是 cont char * str = "hello";(不过现在直接按上面一行不加const这么写会被编译器提示)这样的,“hello”这个字符串被分配在内存中的代码区,该区域是只读的。str指针指向了该区域。因此无法对其内容进行修改。所以就无需在前面加上一个const修饰符了。
总结
1.尽量少用预处理命令,因其不包含类型信息,有人重新修改也不会有产生警告。
2.在实现文件中使用 static const来修饰只在当前文件内使用的常量。
3.在头文件中使用extern来声明全局常量。