Um im Code genau zu sehen, wann was passiert. [...], aber ich will, dass explizit dasteht, was gemacht wird.
Das verstehe ich nicht. Warum willst du das wissen? Wie genau sich das Objekt aufräumt, ist ein Implementierungsdetail, und dass es aufgeräumt wird, garantiert dir der Standard. Wozu willst du das sehen/hinschreiben müssen? Für mich ist das etwas logisch schon implizites, eine Selbstverständlichkeit. Ich würde mich wundern, das hinschreiben zu müssen. Offenbar ist diese Logik noch nicht zu anderen "modernen" OOP-Sprachen durchgedrungen.
Meinetwegen kannst du das in einer hypothetischen Sprache sogar so machen, dass es einen Compilerfehler gibt, wenn ich das Objekt nicht aufräume
Bei Stackobjekten: Okay. Aber wie willst du das bei Objekten am Heap bzw Zeigern auf Objekte lösen? Der Compiler kann nicht wissen, welche Lebenszeit das Ding haben soll. Es kann sogar vorkommen, dass du selbst es nicht weißt, weil es z.B. von äußeren Umständen, wie Spielern auf einem Server abhängt.
Wie gesagt, die Syntax in C++ ist nicht so toll dafür. Zum Beispiel mit Ada sähe das so aus (schnell aus dem Internet zusammenkopiert, weil ich es lang nicht mehr benutzt habe und mit Dateien wohl eh nie was gemacht habe):
[...]
Okay, das ist immerhin schon besser. Aber ich bezweifle, dass diese Fehlerbehandlung in Ada so mächtig ist, wie ein try in anderen Sprachen (Ich kann Ada nicht.). Kann ich damit z.B. nur Fehler in den Zeilen X und Y fangen? Trotzdem: Auch hier kann ich das Freigeben vergessen.
Das kriegt man sich auch nochmal etwas netter formatiert, aber grundsätzlich bist du da syntaktisch schon wieder recht nahe an der expliziten, aber trotzdem übersichtlichen C-Version (da ist halt ein zusätzliches if drin, was auch wieder den möglichen Ablauf genauer klarmacht, aber das könnte man in der hypothetischen Sprache sicher auch noch ein bisschen Syntactic Sugar verpassen):
[...]
Da hier nur eine Resource im Spiel ist, ist alles noch relativ einfach. Sobald es aber mehrere werden, gibts für jede Überprüfung ein if, nur damit der richtige Returncode zurückgegeben wird. Exceptions sind um Welten eleganter, einfacherer und sicherer zu verwenden. (Vorausgesetzt, man hat RAII.)
Und Zeiger/Referenzen können nur im Konstruktor gesetzt werden und nicht irgendwann in der Mitte der Lebenszeit des Objekts? Für mich klingt das nach einem Rezept für subtile Fehler.
Was du mir damit sagen willst, verstehe ich nicht. Es ist ganz natürlich, dass Objekte voneinander abhängen. Indem man die Objekte umgekehrt zu ihrer Erzeugungsreihenfolge zerstört, kann eben nichts schief gehen.
Ich muss es lernen, wenn ich diese Sprache benutzen will.
Jeder Sprache hat ihre Eigenheiten. Außerdem ist das nicht wirklich eine Regel, die viel Lernen bedarf. Meiner Meinung nach ist das eines der logischsten Dinge überhaupt, die man eigentlich gar nicht nachsehen muss.