Scott Meyers bescheidener Meinung nach ist sein Buch das 2. wichtigste C++-Buch nach Bjarne Stroustrups Die C++-Programmiersprache. Gleich danach kommt für ihn Design Patterns von Erich Gamma und Co, welches großen Einfluss auf den Gebrauch von C++ gehabt hatte.
Das am häufigsten gebrauchte Wort in seinem Ratgeber ist Kunde. Für Meyers sind die Kunden nicht nur die Programmierer, die den Code benutzen, sondern der Verfasser des Quelltextes selbst. Das überschneidet sich mit Robert C. Martins Feststellung in Clean Code, dass man sich als Programmierer keineswegs ständig etwas Neues ausdenkt, sondern 9/10 des Tages damit verbringt, seinen eigenen Quelltext zu lesen. Denn natürlich besteht ja der Sinn im Programmieren, Dinge zu verfassen, die wieder verwendet werden.
Hier mal ein paar Beispiel-Tips:
Nach Möglichkeit const verwenden
In C++ gibt es vielfältige Möglichkeiten, const zu verwenden. Wenn man jetzt nicht nur noch darüber nachdenkt (mein Tip), was man alles als const deklarieren könnte, spricht nichts dagegen, es mehr und mehr einzusetzen. Und manche Programmierfehler werden dabei aufgedeckt. Defaultmäßige bitweise Konstanz von Klassenelementen kann nachträglich durch mutable in logische Konstanz aufgeweicht werden. Also nur Mut!
Objekte vor ihrer Verwendung initialisieren
Die Regeln, die definieren, wann ein Objekt initialisiert wird, sind sogar für Meyers zu kompliziert. Eine einfache Regel ist, einfach jedes Objekt vor Verwendung zu initialisieren. Nichtklassenelemente müssen manuell initialisiert werden. Bei Klassenelementen übernimmt diese Aufgabe der Konstruktor. Hier sollte allerdings die Elementinitialisierungsliste verfasst werden. Nur hier ist die Initialisierung ohne Ausnahme gewährleistet. Und man will sich ja über die Regeln keine Gedanken machen müssen. Zudem ist diese Initialisierung oft schneller als über den Umweg des Kopierzuweisungsoperators.
Da die Reihenfolge der Initialisierung nicht lokaler (außerhalb von Funktionen definierter) statischer Objekte in verschiedenen Übersetzungseinheiten (Übersetzungseinheit = Quelltextdatei + eingebundene Header) nicht definiert ist, ergeben sich Probleme wenn ein statisches Objekt ein anderes statisches Objekt benutzen will. Der Kniff besteht hier darin, eine Funktion zu schreiben, die die Referenz auf das statische Objekt zurück gibt. Dies ist eine einfache Anwendung des Singleton Pattern. Das globale statische Objekt wird durch Funktionskapselung lokal und für die Initialisierung von lokalen statischen Objekten übernimmt C++ vor deren Verwendung die Garantie.
Kompilierungsabhängigkeiten zwischen Dateien minimieren
C++ kann schlecht zwischen dem Klasseninterface und der Implementierung unterscheiden. Was in der Klasse Person als private deklariert ist, geht den Kunden nichts an, könnte man denken. Denn der benutzt ja nur die öffentlichen Funktionen. Ändern sich in der Deklaration aber private Daten oder Definitionen, muss alles neu kompiliert werden, was die geänderte Klasse benutzt. Ist die geänderte Klasse noch zentral, und man ist sich in seiner Implementierung noch nicht sicher, muss der Kunde ständig informiert werden, er möge doch erst mal alle Abhängigkeiten finden und gründlich neu kompilieren.
Die Lösung besteht darin, sich von Definitionen unabhängig zu machen und stattdessen von Deklarationen abzuhängen. Wo möglich sollten Klassen foreward deklariert werden. Wenn sich der Aufwand rechtfertigt, könnte man zwei Headerdateien für eine Übersetzungseinheit anlegen, eine mit der Deklaration und eine mit der Definition. Z.B. Bibliotheken, deren ‚Bücher‘ nun mal häufig wiederverwendet werden, sollte man so entwickeln.
Zwei weitere Möglichkeiten, die Abhängigkeit von Definitionen zu vermeiden, sind Handle-Klassen und Interfaces. Wenn die Klasse Person einen Zeiger auf ihre Implementierung (Pimple-Idiom) besitzt und diesen benutzt, um ihre öffentliche Schnittstelle zu implementieren, sind ihre Kunden nur von von ihrer Deklaration abhängig. Die Definition wurde in die Implementierungsklasse verlagert.
Dasselbe Ziel lässt sich mit einem Interface erreichen. Die Klasse Person mutiert zu einer abstrakten Basisklasse. In C++ kann diese im Gegensatz zu Java oder .NET eine Fabrikfunktion beinhalten, die eine konkrete Person erzeugt und einen Zeiger auf die abstrakte Person zurück liefert.