Из-за того, как работают объекты 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 ++, который эквивалентен NSMutableStringObjective-C. Эквивалент моего примера выше будет выглядеть примерно так:
MutableString& f3(const MutableString& x) {
x.appendString(" world!");
return x;
}
Это определенно не скомпилируется: в дополнение к appendString()тому const, что эта функция не является операцией, она удаляет constклассификатор из ссылки на тип, для которого требуется a const_cast.
[*] Я ожидаю, что есть некоторый искаженный способ сделать это, но теперь мы находимся в сферах одного программиста, пытающегося саботировать другого, делая «умные» вещи.