Due to the way that Objective-C objects work, const
gives up being an enforcement and starts being a notation for the programmer. Consider this program:
int f(const int x) {
return ++x;
}
int main(int argc, char *argv[]) {
@autoreleasepool {
int x = 3;
NSLog(@"%d", f(x));
}
return 0;
}
That actually won't compile here (I'm using clang): the compiler can detect the attempt to modify the primitive C type and emits an error. But now compare it with this program:
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;
}
Even though the function is passed a constant pointer to a constant object, it's still possible to mutate the object.
In object-oriented programming, the best way to enforce the constant nature of an object is to make that object immutable - i.e. don't provide any methods that can change its state. Imagine that the function above took an NSString
argument instead of NSMutableString
, and that I'd passed the literal @"Hello"
instead of a mutable copy. There is now, reasonably speaking, no chance of mutating the passed-in object[*]. Objective-C doesn't have any way of enforcing that though, unlike const
or final
object references in other OO languages.
For comparison, const
works entirely differently in C++. If I get a const
reference to a C++ object, I'm only allowed to call const
member functions on that object. These functions preserve the const
-ness of the object, either by not making any changes or by only modifying member variables that have explicitly been marked mutable
by the class designer. So imagine that I had some type MutableString
in C++ that's equivalent to NSMutableString
in Objective-C. The equivalent of my example above would look something like:
MutableString& f3(const MutableString& x) {
x.appendString(" world!");
return x;
}
This definitely won't compile: in addition to appendString()
not being a const
operation, the function removes the const
qualifier from the type reference which requires a const_cast
.
[*]I expect there is some contorted way of doing it, but now we're into the realms of one programmer trying to sabotage another by doing "clever" things.