我理解在头文件中将变量声明放在extern
之前声明了全局静态变量的存在而没有初始化它。我也明白,如果我导入包含extern
变量的文件,我可以在没有类/文件名的情况下引用它们。但是,人们在哪里定义它们及其价值?
我要做的是创建一个具有全局常量的常量类,我想在整个iOS应用程序的代码中使用它。
是否有人将它们放在界面中?
example.h文件
#import <Foundation/Foundation.h>
@interface Constraints : NSObject
{
extern NSString * const PREFS_NAME;
}
或者那个人就像这样放在界面之外
example.h文件
#import <Foundation/Foundation.h>
extern NSString * const PREFS_NAME;
@interface Constraints : NSObject
{
}
然后在实现.m文件中如何初始化extern值?
在这样的实施区域内?
Example.m
#import "Constraints.h"
@implementation Constraints
/**PRefecences name for the application**/
const NSString * PREFS_NAME = @"MyApp_Prefs";
@end
或者在实现区域之外初始化它们,如下所示:
Example.m
#import "Constraints.h"
/**PRefecences name for the application**/
const NSString * PREFS_NAME = @"MyApp_Prefs";
@implementation Constraints
@end
或者我是否在构造函数中为它们提供了初始值?或者一些任意的静态样式方法,前面有+
,即+(void) setAppConstraints
;
我尝试了几种组合,但总会遇到错误,例如“使用不同类型重新定义'xVariable'”。或者关于“extern没有初始化界面”的东西(或类似的东西,我忘了)。所以我想知道如何正确地声明和初始化它们以形成与Java中public static final
变量相同的角色。
extern
命令的限制是什么?我知道我可以extern
NSInteger
或NSString
,但NSArray
呢?
我在问这个问题,因为在Objective-C中使用extern
似乎有很多误导或不完整的信息。许多答案似乎都是猜测性的。我希望这个问题不仅对我来说是一个很好的资源,而且是为了限制关于extern
基础的更多类似问题。
答案 0 :(得分:13)
您在声明它的文件中定义它的值,在您的情况下是Example.m;您仍然可以重新分配此变量,因此Example.h中的声明如下所示:
extern NSString * PREFS_NAME;
这样,导入Example.h的每个文件都可以访问此变量。 Objective-C中公共静态final的等价物是const。如果你也希望它是公共的,你应该把它变成一个类实例变量,但在这种情况下你不需要它,因为它已经可以在任何地方访问。所以在这种情况下它将是:
// .m file
NSString* const PREFS_NAME = @"MyApp_Prefs";
// .h file
extern NSString* const PREFS_NAME;
另请注意,const NSString *与NSString * const不同。后者是指向NSString的const指针。即使它是正确的语法,前者也没有意义。在Objective-C中,const限定符不影响对象,而是有可变和不可变的类。它在C ++中有意义,意味着你可以在实例上使用const方法。
答案 1 :(得分:3)
extern
用于通知编译器您将使用另一个编译单元中定义的变量或函数。
当您说extern const NSString *PREFS_NAME
时,您说“将此编译单元中的所有引用替换为PREFS_NAME”,因为它是在另一个文件中定义的变量PREFS_NAME。因此,当您尝试在.m中分配PREFS_NAME时,您所做的只是尝试分配一个变量,尽管它有一个名称,但它不存在。声明变量extern
只是变量或函数的声明,而不是该变量或函数的定义。它让编译器知道 name 正在使用中,并且链接器将负责如何处理它,但即使你在这里提供了一个类型,它实际上并没有留出空间对于变量,它期望在实际定义变量的编译单元中留出空间。
您可以一起编译三个或四个不同的源代码文件,其中三个可以声明:
extern int buffer[];
可以宣布
int buffer[BUFSIZE];
在其全局范围内,链接器的工作是将对extern buffer
的三个声明引用解析为第四个缓冲区的实际定义。
extern
对于C变量和函数来说就像@class
对于Objective-C类一样,它是一个前向声明,对编译器的承诺,当你看到它时你不必惊慌失措这里的名称未定义,因为链接器将回答您可能遇到的任何遗留问题。