Из-за того, как работают объекты Objective-C, он const
перестает быть принудительным и становится нотацией для программиста. Рассмотрим эту программу:
int f(const int x) {
return ++x;
}
int main(int argc, char *argv[]) {
@autoreleasepool {
int x = 3;
NSLog(@"%d", f(x));
}
return 0;
}
Это на самом деле не скомпилируется (я использую clang): компилятор может обнаружить попытку изменить тип примитива C и выдает ошибку. Но теперь сравните это с этой программой:
NSMutableString *f2(const NSMutableString * const x) {
[x appendString: @" world!"];
return x;
}
int main(int argc, char *argv[]) {
@autoreleasepool {
NSMutableString *x = [@"Hello" mutableCopy];
NSLog(@"%@", f2(x));
}
return 0;
}
Несмотря на то, что функции передается постоянный указатель на постоянный объект, все же возможно изменить объект.
В объектно-ориентированном программировании лучший способ обеспечить постоянную природу объекта состоит в том, чтобы сделать этот объект неизменным, то есть не предоставлять никаких методов, которые могут изменить его состояние. Представьте, что функция выше взяла NSString
аргумент вместо NSMutableString
, и что я передал литерал @"Hello"
вместо изменяемой копии. В настоящее время, по правде говоря, нет никаких шансов поменять переданный объект [*]. Objective-C не имеет никакого способа обеспечить это, в отличие от const
или final
ссылки на объекты в других языках OO.
Для сравнения, const
в C ++ работает совершенно иначе. Если я получаю const
ссылку на объект C ++, мне разрешено вызывать const
функции-члены только для этого объекта. Эти функции сохраняют const
-ность объекта, либо не внося никаких изменений, либо изменяя только переменные-члены, которые были явно помечены mutable
конструктором класса. Итак, представьте, что у меня был какой-то тип MutableString
в C ++, который эквивалентен NSMutableString
Objective-C. Эквивалент моего примера выше будет выглядеть примерно так:
MutableString& f3(const MutableString& x) {
x.appendString(" world!");
return x;
}
Это определенно не скомпилируется: в дополнение к appendString()
тому const
, что эта функция не является операцией, она удаляет const
классификатор из ссылки на тип, для которого требуется a const_cast
.
[*] Я ожидаю, что есть некоторый искаженный способ сделать это, но теперь мы находимся в сферах одного программиста, пытающегося саботировать другого, делая «умные» вещи.