7

我知道将这个词放在extern头文件中的变量声明之前声明了全局静态变量的存在而不初始化它。我也明白,如果我导入包含extern变量的文件,我可以在没有类/文件名的情况下引用它们。但是在哪里定义它们和它们的价值呢?

我想做的是创建一个带有全局常量的常量类,我想在整个 iOS 应用程序的代码中使用它。

是否将它们放在这样的界面中?

例子.h

#import <Foundation/Foundation.h>
@interface Constraints : NSObject
{

extern   NSString * const PREFS_NAME;

}

还是像这样放在界面之外

例子.h

#import <Foundation/Foundation.h>

extern   NSString * const PREFS_NAME;    

@interface Constraints : NSObject
{

}

然后在实现 .m 文件中如何初始化外部值?

在这样的实施区域内?

例子.m

#import "Constraints.h"

@implementation Constraints

/**PRefecences name for the application**/
const  NSString * PREFS_NAME = @"MyApp_Prefs";

@end

或者像这样在实现区域之外初始化它们:

例子.m

#import "Constraints.h"

/**PRefecences name for the application**/
const  NSString * PREFS_NAME = @"MyApp_Prefs";

@implementation Constraints

@end

还是我在构造函数中为它们提供初始值?或一些任意的静态样式方法,+前面有,即+(void) setAppConstraints

我尝试了几种组合,但总是遇到错误,例如“使用不同类型重新定义'xVariable'”。或者关于“外部没有初始化接口”的东西(或者类似的东西,我忘记了)。所以我想知道如何正确地声明和初始化它们以形成与public static finalJava 中的变量相同的角色。

还有什么是extern命令的限制?我知道我可以extern使用NSIntegeror NSString,但那又如何NSArray呢?

extern我问这个问题是因为关于在 Objective-C中使用的信息似乎有很多误导性或不完整的信息。许多答案似乎是推测性的。我希望这个问题不仅对我来说是一个很好的资源,而且可以限制关于extern.

4

2 回答 2

13

您在声明它的文件中定义它的值,在您的情况下是 Example.m;您仍然可以重新分配此变量,因此 Example.h 中的声明如下所示:

extern  NSString * PREFS_NAME;

这样每个导入 Example.h 的文件都可以访问这个变量。Objective-C 中 public static 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 方法。

于 2013-02-16T19:53:11.823 回答
3

extern用于向编译器发出信号,表明您将使用在另一个编译单元中定义的变量或函数。

当您说 时extern const NSString *PREFS_NAME,您是在说“将此编译单元中对 PREFS_NAME 的所有引用替换为在另一个文件中定义的变量 PREFS_NAME。” 因此,当您尝试在 .m 中分配 PREFS_NAME 时,您所做的只是尝试分配一个变量,尽管它有名称,但它并不存在。声明一个变量extern只是一个变量或函数的声明,而不是该变量或函数的定义。它让编译器知道该名称正在使用中,并且链接器将处理如何处理它,但即使您在此处提供了一个类型,它实际上并没有为变量留出空间,它期待在实际定义变量的编译单元中留出空间。

您一起编译三个或四个不同的源代码文件,其中三个可能声明:

extern int buffer[];

并且可以声明

int buffer[BUFSIZE];

在其全局范围内,链接器的工作是将三个声明的引用解析为extern buffer第四个缓冲区的实际定义。

extern对于 C 变量和函数,就像@class对于 Objective-C 类一样,它是一个前向声明,是对编译器的一个承诺,当你在这里看到一个未定义的名称时,你不必惊慌失措,因为链接器会回答任何挥之不去的东西您可能有的问题。

于 2013-02-16T19:17:09.797 回答