2010-12-04 4 views
4

Я искал константы, и я не понимаю, что отличает их от других, кроме того, что они могут быть изменены программно.Объяснение констант

extern NSString * const MyConstant; 

С этой линией, что именно это означает extern и что именно делает const означает?

ответ

19

Здесь вас задают два вопроса: один о константах и ​​один о внешнем. Эти два не обязательно связаны между собой.

Во-первых, const: константы не намного больше, чем, как вы сказали, они не могут быть изменены программно. Различные вещи могут быть постоянными, хотя, в зависимости от того, как вы их объявляете. Например, в вашем примере:

NSString * const MyConstant = @"foo"; 

Вы указали постоянный указатель на непостоянный объект NSString; ключевое слово const находится справа от звезды, поэтому оно относится к указателю. Таким образом, это:

MyConstant = @"bar"; 

приведет к ошибке компиляции, поскольку он пытается передать MyConstant, чтобы указать на другой NSString.

Если ключевое слово const расположено слева от звезды, оно будет ссылаться на объект, на который ссылается указатель (в данном случае лежащая в основе структура NSString). Это, вероятно, не то, что вы хотите большую часть времени в Objective C. Обратите внимание, что положение const ключевого слова относительно идентификатора типа не имеет значения, так это:

const NSString *MyConstant = @"foo"; 

и это:

NSString const *MyConstant = @"foo"; 

означает то же самое.Вы можете также юридически объявить как указатель и эталонное значение сопзЬ, для максимального константность:

const NSString * const MyConstant = @"foo"; 

Во-вторых, ехЬегп: extern просто позволяет объявить переменную в одном модуле компиляции, и пусть компилятор знать, что вы определили эту переменную в отдельном модуле компиляции. Обычно вы используете это только для глобальных значений и констант.

Вы можете представить себе блок компиляции как один файл .m, а также все файлы .h, которые он содержит. Во время сборки компилятор компилирует каждый файл .m в отдельный файл .o, а затем компоновщик соединяет их все вместе в один двоичный файл. Обычно то, как один блок компиляции знает об идентификаторах (таких как имя класса), объявленных в другом модуле компиляции, является импортированием файла заголовка. Но в случае глобалов они часто не являются частью открытого интерфейса класса, поэтому они часто объявляются и определяются в файле .m.

Если модуль компиляции объявляет глобальный в .m файле:

#import "A.h" 

NSString *someGlobalValue; 

и модуль компиляции B хочет использовать, что глобальное:

#import "B.h" 
extern NSString *someGlobalValue; 

@implementation B 

- (void)someFunc { 
    NSString *localValue = [self getSomeValue]; 
    if (localValue isEqualToString:someGlobalValue]) { 
     ... 
    } 
} 

блок B должен каким-то образом указать компилятору использовать переменная, объявленная блоком A. Он не может импортировать файл .m, где происходит объявление, поэтому он использует extern, чтобы сообщить компилятору, что переменная существует в другом месте.

Обратите внимание, что если блок А и блок B как есть эта линия на верхнем уровне файла:

NSString *someGlobalValue; 

то у вас есть две единицы компиляции декларирующих ту же глобальную переменную, и компоновщик не сможет с дублирующейся символьной ошибкой. Если вы хотите иметь переменную, как это, что существует только внутри модуля компиляции, и является невидимым для других единиц компиляции (даже если они используют extern), вы можете использовать static ключевое слово:

static NSString * const someFileLevelConstant = @"wibble"; 

Это может быть полезна для констант, которые вы хотите использовать в одном файле реализации, но не потребуется в другом месте.

+0

Приветствия тем, кто сломает его. Сломай. – 2012-09-30 19:47:00

-1

Extern означает, что переменная установлена ​​за исходным файлом, в котором она была объявлена. Рекомендуется использовать флаг OBJC_EXPORT вместо extern.

Const означает, что переменная не может быть изменена после ее установки. Тем не менее, вы можете использовать некоторый указатель Misdirection, как показано ниже:

NSString **var = (NSString **)&MyConstant; 
*var = @"I changed it!"; 

Это фактически позволит вам изменить его, если вам нужно (например, в классах +initialize метода).

+0

Первый абзац имеет смысл. Остальное не относится к этому вопросу (и на самом деле не имеет смысла). – bbum 2010-12-04 17:16:12

2
extern NSString * const MyConstant; 

Вы увидите это в заголовочных файлах. Он сообщает компилятору, что переменная MyConstant существует и может использоваться в ваших файлах реализации.

Скорее всего, переменная устанавливается что-то вроде:

NSString * const MyConstant = @"foo"; 

Значение не может быть изменено. Если вы хотите, чтобы глобальное значение можно было изменить, отпустите объявление const.

+0

Вы должны редко, если вообще когда-либо, видеть `extern` в файлах заголовков. Существует ключевое слово `extern`, позволяющее компоновщику разрешать символы, используемые в единицах перевода. Не нужно использовать `extern`, если символ объявлен в файле заголовка; просто импортируйте файл заголовка. И не нужно использовать `extern` для импорта символа в заголовочный файл, поскольку глобальные переменные не являются частью интерфейса для класса. – 2010-12-04 19:55:55