Effektiv C++ 22 Tips für besseres C++ basierend auf Ideen von Scott Meyers. Stephan Brumme, 21.Mai 2002

Ähnliche Dokumente
Effektiv C++ programmieren

Programmieren in C++ Überladen von Methoden und Operatoren

C++ - Objektorientierte Programmierung Konstruktoren und Destruktoren

Dynamische Datentypen. Destruktor, Copy-Konstruktor, Zuweisungsoperator, Dynamischer Datentyp, Vektoren

OOP. Kapselung: Gruppierung von Daten und Funktionen als Objekte. Definieren eine Schnittstelle zu diesen Objekten.

Einstieg in die Informatik mit Java

HSR Rapperswil 2001 Markus Rigling. Programmieren: Vererbung. 1 Variante 2

Verschlüsseln eines Bildes. Visuelle Kryptographie. Verschlüsseln eines Bildes. Verschlüsseln eines Bildes

Objektorientiertes Programmieren in C++

Klassen als Datenstrukturen

Was Mathematiker schon vor Jahrhunderten erfunden haben, gibt es jetzt endlich in ihrer Programmiersprache:

Prof. W. Henrich Seite 1

Peter Prinz Ulla Kirch-Prinz C+ + Lernen und professionell anwenden. ffl mitp

Einstieg in die Informatik mit Java

Programmierkurs C/C++

C++ - Objektorientierte Programmierung Konstante und statische Elemente

Objektorientiertes Programmieren mit C++ für Fortgeschrittene

Implementieren von Klassen

Vorlesung Datenstrukturen

7. Übung Informatik II - Objektorientierte Programmierung

Polymorphismus 179. Function.h. #include <string>

Visuelle Kryptographie. Anwendung von Zufallszahlen

Kapitel 8. Programmierkurs. Methoden. 8.1 Methoden

DAP2-Programmierpraktikum Einführung in C++ (Teil 2)

Objektorientierte Programmierung mit C++ SS 2007

Thema heute: Vererbung und Klassenhierarchien. Abgeleitete Klassen. Vererbung von Daten und Funktionen. Virtuelle Funktionen

Überblick. 6. Konstruktor und Destruktor - obligatorische Elementfunktionen einer Klasse

Einstieg in die Informatik mit Java

C++ - Einführung in die Programmiersprache Polymorphismus und Vererbung. Eltern

C++ Klassen weitere Funktionen

C++ Teil 5. Sven Groß. 13. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 18

Grundlagen Polymorphismus Eigenschaften virtueller Klassen Mehrfachvererbung bei ROOT. Mehrfache Vererbung. Daniel Beneckenstein. 21.

Vererbung und Polymorphie

C++ Teil 6. Sven Groß. 27. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 14

Vorlesungsprüfung Programmiersprache 1

C++ - Einführung in die Programmiersprache Header-Dateien und Funktionen. Leibniz Universität IT Services Anja Aue

Lehrstuhl für Datenverarbeitung. Technische Universität München. Grundkurs C++ Typumwandlung

Objektorientiert in C++

Grundkurs C++ IDE Klassenhierarchien

Programmieren II Abstrakte Klassen / Virtuelle Methoden. Programmieren II Abstrakte Klassen / Virtuelle Methoden

Einstieg in die Informatik mit Java

Grundkurs C++ IDE Klassenhierarchien

Lambda-Funktionen. Lambda-Funktionen. Lambda-Funktionen sollen

OOP und Angewandte Mathematik. Eine Einführung in die Anwendung objektorientierter Konzepte in der angewandten Mathematik

7. Schnittstellen Grundlagen zu Schnittstellen. 7. Schnittstellen

Weitere Beispiele. Beispiel CD-Spieler: Exemplare eines abstrakten Konzepts. 7. Schnittstellen. Schnittstelle: Syntax

Vererbung. Gerd Bohlender. Institut für Angewandte und Numerische Mathematik. Vorlesung: Einstieg in die Informatik mit Java 23.5.

Objektorientiertes Programmieren mit C++ für Fortgeschrittene

Programmieren in C++ Templates

7 Vererbung. Modul Programmieren mit C++ Kapitel Vererbung

C++ Teil 9. Sven Groß. 17. Juni Sven Groß (IGPM, RWTH Aachen) C++ Teil Juni / 17

Vererbung, Polymorphie

Programmierung III. Pointer für Fortgeschrittene Marc Ruberg. Arrays von Pointern ( Zeigervektoren ): Pointer auf Pointer:

5.4 Arrays. Oft müssen viele Werte gleichen Typs gespeichert werden. Idee: Lege sie konsekutiv ab! Greife auf einzelne Werte über ihren Index zu!

C++ Teil 12. Sven Groß. 18. Jan Sven Groß (IGPM, RWTH Aachen) C++ Teil Jan / 11

Crashkurs C++ - Teil 1

Umsetzung einer Klassenkarte in einer Programmiersprache

virtual Wertpapier& operator=(const Wertpapier&); // VIRTUELLE ZUWEISUNG protected: static enum {wortfeldlaenge = 20}; char* name_z; double kurs; };

C++ Teil 5. Sven Groß. 8. Mai IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil 5 8. Mai / 16

Mikrorechentechnik II. Klassen in C++

6 ZEIGER UND REFERENZEN - ALLGEMEINES

Wichtige Prinzipien von C#

Thema heute: Vererbung und Klassenhierarchien. Abgeleitete Klassen. Vererbung von Daten und Funktionen. Virtuelle Funktionen

3. Klassen Statische Komponenten einer Klasse. Klassenvariablen

Teil 8: Dynamische Speicherverwaltung. Prof. Dr. Herbert Fischer Fachhochschule Deggendorf Prof. Dr. Manfred Beham Fachhochschule Amberg-Weiden

1. Referenzdatentypen: Felder und Strings. Referenz- vs. einfache Datentypen. Rückblick: Einfache Datentypen (1) 4711 r

1. Referenzdatentypen: Felder und Strings

Vorkurs Informatik: Erste Schritte der Programmierung mit C++

C++ Notnagel. Ziel, Inhalt. Programmieren in C++

Themen. Statische Methoden inline Methoden const Methoden this Zeiger Destruktor Kopierkonstruktor Überladen von Operatoren

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 29

Objektorientierte Programmierung. Kapitel 22: Aufzählungstypen (Enumeration Types)

Informatik 1 ( ) D-MAVT F2011. Klassen, Funktionen. Yves Brise Übungsstunde 9

C++ für Dummies. Stephen R. Davis. Gegen den täglichen Frust mit C++ Übersetzung aus dem Amerikanischen: Judith Muhr.

Liste Programmieren Java Überblick

Einleitung Typsystem Typisierung Zusammenfassung Literatur. Typisierung. Effiziente Programmierung. Thomas Schnieders

4. Vererbung. Idee der Vererbung. Wir wollen ein Verwaltungsprogramm für CDs und Videos entwickeln. Wir stellen uns dazu folgende Klassen vor:

Datenkapselung: public / private

Überblick. Überblick zum weiteren Inhalt

Klassenmethoden. Klassenvariablen. Für das Auslesen des Studentenzählers definieren wir eine öffentliche Klassenmethode:

C++ Teil 10. Sven Groß. 17. Dez IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Dez / 14

C# - Einführung in die Programmiersprache Methoden. Leibniz Universität IT Services

Programmieren in C++ Klassen

Methoden. von Objekten definiert werden, Methoden,, Zugriffsmethoden und Read-Only

Programmieren in C++ Vererbung

Werner Achte rt DATA BECKER

Kapitel 2 Elementare Datentypen, Konstanten und Variablen Elementare Datentypen

Überblick. 5. Objekt und Klasse, Elementfunktionen

Einführung in die Programmierung mit C++

Systemnahe Programmierung in C/C++

Grundlagen der Informatik

Vorlesung Programmieren

Vererbung I. Kfz Eigenschaften und Methoden der Klasse Kfz Lkw. Pkw. Eigenschaften und Methoden der Klasse Kfz

3D Programmierpraktikum: Einführung in C++ - Teil 2

1 Klassen und Objekte

C++ - Einführung in die Programmiersprache Zeiger, Referenzen und Strukturen. Leibniz Universität IT Services Anja Aue

Überblick. Überblick. Abstrakte Klassen - rein virtuelle Funktionen Beispiele

Einführung in C# Teil 1. Matthias Nübling

C++ Klassen, Vererbung. Philipp Lucas. Sebastian Hack. Wintersemester 2008/09. saarland.

Tag 8 Repetitorium Informatik (Java)

Transkript:

1 22 Tips für besseres C++ basierend auf Ideen von Scott Meyers

Gliederung 2 1. Einführung 2. Der Umstieg von C nach C++ 3. Konstruktoren, Destruktoren und Zuweisungsoperatoren 4. Entwurf und Deklaration von Klassen und Funktionen

Einführung 3 Begriff Deklaration : Mitteilung des Namens und Typs - eines Objekts, - einer Funktion, - einer Klasse oder - eines Templates z.b.: extern string strhostname; string GetHostname(int nlocalip); class CServer; template<class T> class CStack;

Einführung 4 Begriff Definition : Festlegung des Aufbaus und der Struktur der Compiler kann für ein Objekt Speicher bereitstellen eine Funktionsdefinition enthält den kompletten Funktionsrumpf eine Klasse oder ein Template zählt die Elemente auf

Einführung 5 Initialisierung: erstmalige Wertzuweisung an ein Objekt wird immer automatisch direkt nach der Erzeugung eines Objekts einer Klasse durchgeführt keine Initialisierung von in C++ eingebauten Typen! Zuweisung: Wertzuweisung an ein bereits initialisiertes Objekt eventuell Freigabe von alloziierten Ressourcen notwendig

Einführung 6 Konstruktor: diejenige(n) Methode(n) einer Klasse, die zur Initialisierung aufgerufen werden Defaultkonstruktor: Konstruktor, der keine Parameter benötigt oder für alle Parameter jeweils einen Standardwert kennt Copy-Konstruktor: Initialisierung eines Objekts als Kopie eines anderen, welches vom gleichen Typ ist

Einführung 7 Destruktor: diejenige Methode einer Klasse, die zur Zerstörung eines Objekts aufgerufen wird es existiert immer nur ein Destruktor pro Klasse

Einführung 8 Compiler erzeugt automatisch: Default-Konstruktor, wenn überhaupt kein Konstruktor vorhanden ist Copy-Konstruktor und Zuweisungsoperator, wenn diese notwendig sind Destruktor diese können und sollten aber vom Programmierer selbst geschrieben werden noch einige Operatoren mehr (siehe Vortrag Teil 2)

Der Umstieg von C nach C++ 9 Tip 1: Vermeidung von Problemen des Präprozessors Präprozessor führt lediglich Textersetzung durch, d.h. hat keinerlei tiefere Kenntnisse der Sprache C++ neue C++ Techniken sind typsicher: - Definition von Konstanten immer mit dem Schlüsselwort const vornehmen - generische Funktionen oder Klassen als Templates implementieren

Der Umstieg von C nach C++ 10 Tip 2: Kommentare aus C bekannte Kommentare sind zeilenübergreifend, können aber nicht verschachtelte C-Kommentare überdecken: /* something */ in C++ neuer Kommentartyp: // something - nur bis zum jeweiligen Zeilenende - kann beliebige Zeichen und Kommentare überdecken

Der Umstieg von C nach C++ 11 Tip 3: Neue I/O-Routinen Definition von typsicheren Eingabe-/Ausgabefunktionen in iostream für alle Standarddatentypen von C++ gleiche syntaktische Form von Objekten bei Lese- und Schreibzugriffen deutlich weniger Fehlermöglichkeiten als bei C, da Datentyp nicht explizit angegeben werden muss i.d.r. ähnliche Effizienz

Der Umstieg von C nach C++ 12 Tip 4: Geänderte Speicherverwaltung nur new und delete rufen bei dynamisch erzeugten Objekten den Konstruktor und Destruktor auf als Operatoren für jede Klasse überladbar mit malloc angelegten Speicher nie mit delete freigeben (gleiches gilt für new in Zusammenspiel mit free)

Der Umstieg von C nach C++ 13 Tip 4: Sichere Typkonvertierungen Upcast ohne zusätzliche Syntax möglich sonst pziel = dynamic_cast<zieltyp>(pquelle); Downcast polymorpher Objekte mit dynamic_cast - Überprüfung des Typs erfolgt zur Laufzeit - wenn fehlgeschlagen: Rückgabe von NULL bzw. bad_cast-exception - Aktivierung von Runtime Type Information (RTTI) erforderlich - geringer zusätzlicher Laufzeitaufwand - sicherster Cast

Der Umstieg von C nach C++ 14 einfacher Cast in Klassenhierarchien mit static_cast - keine tiefe Typprüfung wie bei dynamic_cast möglich - wird während der Kompilierung vorgenommen - kein RTTI notwendig, kein Laufzeitoverhead - empfohlen, wenn Laufzeit große Rolle spielt Unterdrückung der const-eigenschaft eines Objektes mit const_cast - Benutzung nur in Ausnahmefällen sinnvoll, meist in fehlerhaftem Klassenentwurf begründet

Der Umstieg von C nach C++ 15 Konvertierung zwischen Zeigern gleicher Bitbreite mit Hilfe von reinterpret_cast - ist i.d.r. immer möglich, da auf modernen Systemen alle Zeiger gleich breit sind - vollkommen sinnentstellte Typkonvertierungen sind erlaubt - sollte nicht benutzt werden C-Cast erlaubt sämtliche Typkonvertierungen ohne Überprüfung - Syntax: pziel = (Zieltyp)pQuelle; - sollte nicht benutzt werden

Konstruktoren, Destruktoren und Zuweisungsoperatoren 16 Tip 6: Initialisierung vs. Zuweisung im Konstruktor Attribute können initialisiert werden, bevor man den Code des Konstruktors ausgeführt: class Class { Class(MyType Variable) : Attribut(Variable) {... } } erforderlich für const- und Referenzattribute sinnvoll, wenn Copy-Konstruktor des Attributes effizienter als Initialisierung+Zuweisung ist

Konstruktoren, Destruktoren und Zuweisungsoperatoren 17 Tip 7: Reihenfolge der Initialisierung im Konstruktor alle Attribute werden stets in der Reihenfolge initialisiert, in der sie deklariert sind Reihenfolge der Aufzählung in der Inititialisierungsliste des Konstruktors ist irrelevant! Abhängigkeiten zwischen zu initialisierenden Attributen daher minimieren

Konstruktoren, Destruktoren und Zuweisungsoperatoren 18 Tip 8: Virtuelle Destruktoren nach einem Upcast kann Compiler nicht mehr den korrekten Destruktor finden, falls er nicht-virtuell ist, er nimmt den der momentanen Klasse, nicht den der ursprünglichen nicht alle Ressourcen werden korrekt freigegeben Ausweg: Deklaration des Destruktors als virtual wenn Destruktor der Basisklasse virtual ist, dann sind es automatisch alle abgeleiteten, auch ohne explizites virtual für jede Klasse, die als Basisklasse dienen soll, ist virtueller Destruktor empfohlen aber für leichtgewichtige Klassen bedeutet evtl. virtuelle Methodentabelle erheblichen Aufwand

Konstruktoren, Destruktoren und Zuweisungsoperatoren 19 Tip 9: Copy-Konstruktor und Zuweisungsoperator für Klassen mit dynamisch alloziiertem Speicher C++ erzeugt automatisch Copy-Konstruktor und Zuweisungsoperator für jede Klasse, wenn diese nicht existieren - generieren bitweise Kopie mit optimalem Maschinencode Adressen von Zeigern werden kopiert, aber nicht das, worauf sie verweisen falsch richtig Zeiger Zeiger Kopiertes Objekt Zeiger Originalobjekt Originalobjekt Zeiger Kopiertes Objekt

Konstruktoren, Destruktoren und Zuweisungsoperatoren 20 nur wenn min. ein Attribut dynamisch Speicher alloziiert, dann sollten ein eigener Copy-Konstruktor und ein Zuweisungsoperator deklariert und definiert werden - Kopie der alloziierte Ressourcen durchführen - ansonsten Standardimplementierung nutzen, da diese optimal ist bei Erweiterungen der Klasse um neue Attribute den Copy- Konstruktor und Zuweisungsoperator um diese ergänzen

Konstruktoren, Destruktoren und Zuweisungsoperatoren 21 Tip 10: Copy-Konstruktor und Zuweisungsoperator in Klassenhierarchien Objekt kann Attribute der Basisklasse nicht kopieren, wenn diese private sind, da Zugriff verboten ist Lösung: im Copy-Konstruktor/Zuweisungsoperator Aufruf des Copy-Konstruktors/Zuweisungsoperators der Basisklasse CClass(const CClass& obj) : CBaseClass(obj)... {... } CClass& operator=(const CClass& obj) {... CBaseClass::operator=(obj); }...

Konstruktoren, Destruktoren und Zuweisungsoperatoren 22 Tip 11: Rückgabewert des Zuweisunsoperators Verkettung soll erlaubt sein: a = b = c; Rückgabe des linken Objekts, wegen Effizienz als Referenz CClass& operator=(const CClass& obj) {... return *this; } Lehrmeinung ist: Rückgabewert nicht const, damit (a = b) = c zugelassen wird ich empfehle trotzdem const!

Konstruktoren, Destruktoren und Zuweisungsoperatoren 23 Tip 12: Prüfung auf Selbstzuweisung über Aliasing-Effekte ist Zuweisung eines Objekts an sich selbst möglich normale Reihenfolge bei Zuweisung: - Freigabe der Ressourcen des zu überschreibenden Objekts - Kopie der neuen Ressourcen Kopie scheitert, wenn dasselbe Objekt bereits alle Ressourcen freigegeben hat Prüfung auf Objektidentität reicht i.d.r. aus if (this == &obj)... Problem nicht nur auf Zuweisungsoperator beschränkt alle Methoden, die die eigene Klasse als Parameter akzeptieren, sind betroffen

Entwurf & Deklaration von Klassen 24 Tip 13: Vollständige aber minimale Schnittstellen jede Klasse soll alle sinnvollen Anforderungen an sie erfüllen zu große Funktionalität ist kontra-produktiv: - hoher Einarbeitungsaufwand - aufwändige Wartung - Gefahr von Inkonsistenzen minimal empfohlene Schnittstelle: - (Default-) Konstruktor - Destruktor - Copy-Konstruktor und Zuweisungsoperator (Tip 9) meist von Vorteil: - Serialisierungsmechanismus - Überprüfung der Klasseninvariante

Entwurf & Deklaration von Klassen 25 Tip 14: Keine öffentlichen Attribute Verlust der Kontrolle über Lese- und Schreibzugriffe Gefahr von Inkonsistenzen keine Möglichkeit der späteren Ersetzung einer Zuweisung durch eine Berechnung/Überprüfung+Zuweisung funktionale Abstraktion: - jedes Attribut vor Zugriff von außen schützen - Bereitstellung von Lese- und/oder Schreibmethoden - Deklaration als inline erlaubt Compiler meist Eliminierung des Laufzeitoverheads einer Methode

Entwurf & Deklaration von Klassen 26 Tip 15: Methoden vs. globale Funktionen möglichst viele Funktionen sollten Methoden sein - virtuelle Funktionen müssen Methoden sein nur globale Funktionen erlauben implizite Typumwandlung des linken Arguments - sinnvoll z.b. wenn linkes Argument Konstante ist - für Zugriff auf private Attribute ist Deklaration innerhalb der Klasse als friend erforderlich

Entwurf & Deklaration von Klassen 27 Tip 16: Benutzung von const const bedeutet Unveränderbarkeit des attributierten Symbols Wirkung auf - Methoden: kein Attribut des Objekts darf verändert werden - Objekte: nur Aufruf von const-methoden und Lesezugriffe auf Attribute erlaubt Compiler überprüft bitweise Konstantheit zwar nicht Zeiger selbst, aber deren Inhalt ist manipulierbar Ausnahme für Attribute mit Schlüsselwort mutable

Entwurf & Deklaration von Klassen 28 generell existieren bei Zeigern gibt es drei Fälle von const: - das, worauf gezeigt wird, darf nicht verändert werden: const Typ* Variable = Wert; - der Zeiger selbst darf nicht verändert werden: Typ* const Variable = Wert; - weder der Zeiger noch der Inhalt darf geändert werden: const Typ* const Variable3 = Wert;

Entwurf & Deklaration von Klassen 29 Tip 17: Übergabe via Wert vs. Referenz Referenz vermeidet Aufruf des Copy-Konstruktors const, wenn Argument nicht verändert werden braucht/darf Wertübergabe nimmt ggf. Typkonvertierung auf Basisklasse vor oft unerwünscht Referenz arbeitet intern mit Zeigern, d.h. wenn Datentyp sehr klein ist, dann sind Wertübergaben effizienter für alle C++ Basistypen (außer STL) ist Wertübergabe sinnvoll sonst immer (konstante) Referenz benutzen

Entwurf & Deklaration von Klassen 30 Tip 18: Rückgabe einer Referenz zwar effizient für große Objekte, aber meist keine vollständige Kontrolle: - Veränderungen durch andere Objekte möglich - Zerstörung des Objektes denkbar nur sinnvoll für langlebige Objekte, const idealerweise benutzen Einsatz in der Praxis oft auf mathematische Operatoren beschränkt dynamisch erzeugte Objekte immer per Wert zurückgeben

Entwurf & Deklaration von Klassen 31 Tip 19: Überladung vs. Default-Parameter Methoden, die unter gleichem Namen in einer Klasse auftauchen, müssen diese Entscheidung treffen Default-Parameter optimal, wenn der verwendete Algorithmus der Methoden ähnlich oder identisch ist sonst Überladung einsetzen

Entwurf & Deklaration von Klassen 32 Tip 20: Mehrdeutigkeiten implizite Typkonvertierungen können zu Mehrdeutigkeiten führen - treten oft unbewusst auf signaturgleiche Methoden in Basisklassen sorgen bei Mehrfachvererbung auch für Mehrdeutigkeiten zwei Reaktionen möglich: - Compiler kann keine Entscheidung treffen Fehlermeldung - fehlerhaftes Kompilat als explicit deklarierter Konstruktor verhindert implizite Konvertierungen

Entwurf & Deklaration von Klassen 33 Tip 21: Verbot automatisch generierter Methoden in einigen Fällen ist Copy-Konstruktor bzw. Zuweisungsoperator nicht erwünscht Deklaration als private ohne anschließende Definition

Entwurf & Deklaration von Klassen 34 Tip 22: Unterteilung des Namensraums in großen Projekten oftmals Symbole mehrfach verwendet Namenskollisionen durch Compiler / Linker nicht auflösbar eigene Namensräume mit namespace schaffen Benutzung von Symbolen des Namensraumes durch Namensraum::Symbol Einbindung eines Symbols in den eigenen Namensraum mit using Namensraum::Symbol, danach per Symbol verfügbar kompletten Namensraum mit using namespace Namensraum inkludieren

Entwurf & Deklaration von Klassen 35 Literaturverzeichnis Scott Meyers: programmieren, 3.Auflage, Addison-Wesley Longman, Bonn, 1998 Hinweis: Die Nummerierung in diesem Buch unterscheidet sich von meiner, die grobe Reihenfolge der Tips ist aber ähnlich Weiter empfehlenswert: - Bjarne Stroustrup: Die C++ Programmiersprache, 3.Auflage, Addison-Wesley Longman, Bonn, 1998 - Bruce Eckel: Thinking in C++ Band 1&2, 2.Auflage, Prentice Hall, Upper Saddle River, 2000 kostenlos im PDF-Format erhältlich unter www.bruceeckel.com