Aufgrund der Funktionsweise von Objective-C-Objekten wird constdie 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 NSStringstattdessen ein Argument angenommen NSMutableStringund @"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 constoder finalObjektreferenzen in anderen OO-Sprachen.
Zum Vergleich constfunktioniert das in C ++ ganz anders. Wenn ich einen constVerweis auf ein C ++ - Objekt erhalte , darf ich nur constMember-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 mutablevom Klassendesigner explizit markiert wurden. Stellen Sie sich vor, ich hätte einen Typ MutableStringin C ++, der dem NSMutableStringin 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 constOperation, sondern entfernt das constQualifikationsmerkmal 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.