Определение статического члена в target-C и Objective-C++
У меня есть разница при компиляции source-c и source-C++.
Вот объявление Class1 и Class2 в test.h:
#import <Foundation/Foundation.h>
@interface Class1 {
}
@end
@interface Class2 {
}
@end
Теперь это реализация Objective-C в test.m:
#import "test.h"
@implementation Class1
/* static member */
static int mystatic;
@end
@implementation Class2
/* static member */
static int mystatic;
@end
Я успешно компилирую с этой командой:
gcc -arch armv6 -isysroot /Developer/.../iPhoneOS5.0.sdk -x objective-c -c test.m
Теперь я использую именно эту реализацию Objective-C++ test.mm (точно такой же источник):
#import "test.h"
@implementation Class1
/* static member */
static int mystatic;
@end
@implementation Class2
/* static member */
static int mystatic;
@end
И скомпилируйте с этой командной строкой (разница в опции -x):
gcc -arch armv6 -isysroot /Developer/.../iPhoneOS5.0.sdk -x objective-c++ -c test.mm
Но я получаю ошибку:
test.mm:11 error: redefinition if 'int mystatic'
Почему я получаю эту ошибку в ObjC++, а не в ObjC?
1 ответ
Это сводится к разнице между C и C++. В C все в порядке, чтобы переопределить статическую переменную с тем же именем и тем же типом; в C++ делать то же самое - ошибка.
Из стандарта С:
Объявление идентификатора для объекта, который имеет область файла без инициализатора и без спецификатора класса хранения или со статическим спецификатором класса хранения, составляет предварительное определение. Если модуль перевода содержит одно или несколько предварительных определений для идентификатора, а модуль перевода не содержит внешних определений для этого идентификатора, то поведение точно такое, как если бы модуль перевода содержал объявление области файла для этого идентификатора с составным типом как конца блока перевода, с инициализатором, равным 0.
Из стандарта C++:
C.1.2, 3.1 Изменение: C++ не имеет "предварительных определений", как в C. Например, на уровне файла,
int i ;
int i ;
допустим в C, [но он] недействителен в C++.
Что касается Цели C, язык не поддерживает переменные, ограниченные областью действия на уровне класса; декларирование static int mystatic;
внутри @implementation
блок имеет точно такой же эффект, как и объявление его вне @implementation
блок. Чтобы эмулировать переменные в области классов, используйте статические переменные в области функций внутри методов класса.