2014-12-11 3 views
4

В моих проектах iOS/Objective C у меня часто есть файл constants.h с ключами API и т. Д. До сих пор я был объявляя свои константы, как staticconst так:Как статический const отличается от extern const?

static NSString * const kAPIKey = @"wembvkejrvb43789gvbiu2bvfake"; 

Это прекрасно работает, но с неудачной нижней стороной, что я могу только создать константы для примитивов и NSString литералов, по существу. Другие объекты, такие как объекты UIColor, не могут быть сохранены в этой константе , поскольку они не могут быть инициализированы синтаксисом статического литерала (мое понимание, требуется ссылка).

После прочтения некоторых докторов C++, я понимаю несколько вещей:

  • static является ненужным, так как const неявно статичным.
  • Вызов NSString * const x фактически объявляет постоянное и неизменяемое значение в x. Я не могу изменить значение, но могу изменить то, на что указывает x.
  • Этот const имеет внутренний linkage, что означает, что значение определено сразу (предположительно во время компиляции).

Правильно ли эти выводы?

Каким образом extern const отличается? Я предполагаю, что они связаны извне (таким образом, ключевое слово extern). Определены ли они во время выполнения? Могу ли я создать своего рода динамическийextern const, который может быть установлен со значением, возвращаемым методом класса?

Например, я хотел бы создать константу с глобальным охватом, содержащую значение UIColor. Я хотел бы построить это значение цвета, используя метод класса [UIColor colorWithRed:green:blue:alpha:]. Это явно не работает с внутренне связанными константами, которые я использовал (я предполагаю, потому что это происходит во время компиляции), но возможно ли использование внешней константы, возможно, настроенной в методе +initialize?

Любое уточнение деталей такого поведения было бы очень полезно.

ответ

8

Статичность не нужна, поскольку константа неявно статична.

Нет, это неправда.

static При использовании в области видимости файла (то есть вне любого метода или функции) означает, что переменная видна только внутри этого файла.

extern означает, что переменная определена в каком-либо другом файле.

const означает, что переменная не может быть изменена.

Рассмотрите строки. Часто вы будете иметь файл реализация (имя заканчивается в ом), который определяет некоторый постоянный указатель на строку:

NSString *const SomeString = @"some string"; 

Вы можете использовать ту же константу из других файлов.Если да, то вы можете добавить объявление в заголовок (имя заканчивается на .h файл), который объясняет компилятору, что переменная определена в другом месте:

extern NSString *const SomeString; 

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

static NSString *const SomeString = @"some string"; 

и что бы предотвратить его использование за пределами файла.

Вызов NSString * const x фактически объявляет постоянное и неизменяемое значение в x. Я не могу изменить значение, но могу изменить то, на что указывает x.

Правильно, он объявляет указатель x постоянным - его нельзя изменить. Вы также не можете изменить значение, на которое оно указывает, если оно действительно NSString, потому что экземпляр NSString не изменен.

Эта константа имеет внутреннюю связь, что означает, что значение определено сразу (предположительно во время компиляции).

Я возьму 5-е место на этом - я не уверен точно, как компилятор имеет дело с постоянными строками. Я думаю, что безопасно использовать это как ментальную модель; строка будет в любом случае определена до того, как ваш код когда-либо будет использовать ее.

+0

Если 'static' limits scope и' extern' означает, что переменная определена в другом месте, мне даже не нужна 'extern' для глобальной константы? Я могу использовать 'NSString * const SomeString = @" Some String "' в заголовке и получить доступ к SomeString из любого файла, который импортирует этот заголовок?Иными словами, для глобальных констант требуется 'extern'? – cdstamper

+0

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

+0

Очень интересно. Поэтому мой шаблон 'static const' работал только потому, что я объявлял их вне любого класса в пустом файле заголовка, который затем был включен в другое место. Константы 'extern' всегда определяются во время компиляции с использованием принятых литералов или есть способ создать« динамическую »константу (возможно, определенную в + инициализации). – cdstamper

1

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

Но вы все еще можете сделать это элегантно во время выполнения, без какого-либо дополнения к глобальной области видимости, то же образом делает ... SDK

@interface UIColor (RainbowAddition) 

+ (UIColor *)chartruseColor; 

@end 

@implementation UIColor (RainbowAddition) 

+ (UIColor *)chartruseColor { 
    // bonus: this is really chartruse... according to the internet 
    return [self colorWithRed:0.5 green:1.0 blue:0.0 alpha:1.0]; 
} 

@end 

http://cloford.com/resources/colours/500col.htm

+0

Я, безусловно, понимаю логическое решение моей проблемы, спасибо за ответ. Я просто пытаюсь понять основные причины. Я знаю, что литералы (за исключением контейнерных литералов), кажется, создаются во время компиляции; Я просто не понимаю, почему. – cdstamper

+0

@cdstamper - это не литералы, созданные во время компиляции, а объекты, которые могут быть описаны литералами. Причина, по которой могут быть созданы только те, которые могут быть созданы во время компиляции, заключается в том, что только компиляторы могут быть описаны компилятором в виде последовательности входных токенов (в соответствии с определением языка, которое значительно улучшилось в clang 3.6, чтобы включить числа и массивы и словари). – danh

1

Objective-C является чистым продолжением C, C++ - нет.

В глобальной области:

  • в С (и Objective-C) записи const эквивалентно extern const (внешней связи);
  • в C++ письменной форме const эквивалентно static const (внутренняя связь).

И в С (и Objective-C) и C++ для создания глобальной областью действия const вы можете определить это, только один раз, в одном исходном файле, как extern const TYPE identifier = VALUE; и объявить его (обычно в заголовочном файле) например: extern const TYPE identifier; (читайте: я определил эту константу в другом месте на уровне глобальной связи).

Смежные вопросы