Объяснение констант - PullRequest
       2

Объяснение констант

4 голосов
/ 04 декабря 2010

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

extern NSString * const MyConstant;

С этой строкой, что именно означает extern и что именно означает const?

Ответы [ 3 ]

19 голосов
/ 04 декабря 2010

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

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

NSString * const MyConstant = @"foo";

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

MyConstant = @"bar";

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

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

const NSString *MyConstant = @"foo";

, и это:

NSString const *MyConstant = @"foo";

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

const NSString * const MyConstant = @"foo";

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

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

Если модуль компиляции A объявляет глобальный объект в файле .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, чтобы сообщить компилятору, что переменная существует в другом месте.

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

NSString *someGlobalValue;

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

static NSString * const someFileLevelConstant = @"wibble";

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

2 голосов
/ 04 декабря 2010
extern NSString * const MyConstant;

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

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

NSString * const MyConstant = @"foo";

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

0 голосов
/ 04 декабря 2010

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

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

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

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

...