Aufgrund der Funktionsweise von Objective-C-Objekten wird const
die Durchsetzung aufgegeben und es wird eine Notation für den Programmierer. Betrachten Sie dieses Programm:
int f(const int x) {
return ++x;
}
int main(int argc, char *argv[]) {
@autoreleasepool {
int x = 3;
NSLog(@"%d", f(x));
}
return 0;
}
Das wird hier eigentlich nicht kompiliert (ich verwende Clang): Der Compiler kann den Versuch erkennen, den primitiven C-Typ zu ändern, und gibt einen Fehler aus. Aber jetzt vergleiche es mit diesem Programm:
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;
}
Obwohl der Funktion ein konstanter Zeiger auf ein konstantes Objekt übergeben wird, ist es dennoch möglich, das Objekt zu mutieren.
Bei der objektorientierten Programmierung besteht die beste Möglichkeit, die Konstanz eines Objekts durchzusetzen, darin, das Objekt unveränderlich zu machen - dh keine Methoden bereitzustellen, die seinen Zustand ändern können. Stellen Sie sich vor, die obige Funktion hätte NSString
stattdessen ein Argument angenommen NSMutableString
und @"Hello"
statt einer veränderlichen Kopie das Literal übergeben . Vernünftigerweise besteht jetzt keine Chance mehr, das übergebene Objekt zu mutieren [*]. Objective-C hat jedoch keine Möglichkeit, dies zu erzwingen, im Gegensatz zu const
oder final
Objektreferenzen in anderen OO-Sprachen.
Zum Vergleich const
funktioniert das in C ++ ganz anders. Wenn ich einen const
Verweis auf ein C ++ - Objekt erhalte , darf ich nur const
Member-Funktionen für dieses Objekt aufrufen . Diese Funktionen erhalten die const
-ness des Objekts, indem sie entweder keine Änderungen vornehmen oder nur Elementvariablen ändern, die mutable
vom Klassendesigner explizit markiert wurden. Stellen Sie sich vor, ich hätte einen Typ MutableString
in C ++, der dem NSMutableString
in Objective-C entspricht. Das Äquivalent meines obigen Beispiels würde ungefähr so aussehen:
MutableString& f3(const MutableString& x) {
x.appendString(" world!");
return x;
}
Dies wird definitiv nicht kompiliert: Die Funktion ist appendString()
nicht nur keine const
Operation, sondern entfernt das const
Qualifikationsmerkmal aus der Typreferenz, für die a erforderlich ist const_cast
.
[*] Ich gehe davon aus, dass es eine verdrehte Vorgehensweise gibt, aber jetzt befinden wir uns im Bereich eines Programmierers, der versucht, einen anderen zu sabotieren, indem er "clevere" Dinge tut.