Einführung in C++ Kapitel 8 — Mehr Vererbungslehre

Im letzten Kapitel haben wir uns ein Modell mit Fortbewegungsmöglichkeiten zusammengezimmert, um das Konzept der Vererbung zu illustrieren. Wir werden dieses Modell in diesem Kapitel fortführen, um einige Feinheiten der Vererbung und mögliche Anwendung zu demonstrieren. Wenn es schon längere Zeit her ist, dass Du das Kapitel 7 durchgelesen hast, wäre es eine gute Idee, dieses Kapitel noch einmal kurz zur Hand zu nehmen, als Vorbereitung auf ein eingehenderes Studium der dort besprochenen Konzepte.

Neuorganisierte Dateistruktur mit inline-Funktionen

Beispielprogramm: VERERB1.CPP

Wenn Du Dir das Programm VERERB1.CPP etwas genauer ansiehst, wirst Du bemerken, daß es sich um das Programm ALLEVEH.CPP handelt, das wir in Kapitel 7 entwickelt haben. Der Code wurde nur neu arrangiert. Der größte Unterschied ist, daß einige der einfacheren Funktionen zu inline-Funktionen umfunktioniert wurden. Solche kurzen Funktionen solltest Du immer inline deklarieren, da dies nicht nur weniger Schreibarbeit für Dich bedeutet, sondern auch die Abarbeitungsgeschwindigkeit erhöht.

Die andere Änderung ist die der Anordnung von Klassen und deren Methoden, wobei wir zuerst alle Klassen definieren, gefolgt vom Hauptprogramm. Damit haben wir alle Schnittstellendefinitionen auf einer Seite, was das Studium des Code etwas erleichtern sollte. Die Implementationen der Methoden kommen ganz zum Schluß, wo sie auch bei der Hand sind, aber sie stören nicht die Klassendefinitionenen, die wir uns in diesem Kapitel etwas genauer ansehen wollen. Das sollte Dir zeigen, daß die Anordnung von Klassen und Methoden in C++ sehr flexibel erfolgen kann. Natürlich hast Du auch bemerkt, daß wir hier gegen die Natur von C++ und ihr Konzept der getrennten Kompilation verstoßen. Am besten sollten alle Dateien so aufgeteilt werden wie wir es in Kapitel 7 getan haben.

Wie wir schon erwähnt haben, kennen beide abgeleiteten Klassen, Auto und Laster eine Variable mit dem Namen Passagieranzahl, was erlaubt ist. Die Klasse Auto hat eine Methode, Initialisiere(), die denselben Namen trägt wie eine Methode der Superklasse mit dem Namen Vehikel. Die Neuordnung der Dateien ändert nichts an der Legalität dieses Konstrukts.

Wenn Du Dich überzeugt hast, daß diese Datei identisch mit dem Programm ALLEVEH.CPP aus Kapitel 7 ist, kompiliere es und führe es aus. Da wir alles in eine Datei gezwängt haben, benötigst Du dafür auch kein "make" mehr. Das ist auch einer der Gründe, warum wir für dieses Kapitel diese Form gewählt haben: das kompilieren geht schneller und einfacher.

Der scope Operator in C++

Da die Methode Initialisiere() in der abgeleiteten Klasse Auto deklariert wird, versteckt sie die Methode mit demselben Namen, die ein Element der Basisklasse ist. Es kann aber vorkommen, daß Du die Methode der Basisklasse in der abgeleiteten Klasse verwenden willst. Das erreichst Du, indem Du den scope Operator im Hauptprogramm folgendermaßen verwendest:

Sedan.Vehikel::Initialisiere(4, 1600.0);

Wie Du vermuten wirst, müssen Anzahl und Typ der Parameter mit denen der Methode der Basisklasse übereinstimmen, da diese auf diese Nachricht antwortet.

Was sind geschützte Daten in C++?

Wären alle Daten der Basisklasse in allen von dieser abgeleiteten Klassen verfügbar, wäre es für die Programmiererin eine leichte Übung, die Basisklasse zu ererben und auf alle Daten freien Zugriff zu haben. Das würde den Zugriffsschutz komplett ausschalten. Aus diesem Grund sind die Daten einer Klasse in einer von dieser abgeleiteten Klasse nicht automatisch verfügbar. Es kommt aber vor, daß Du alle Variablen in die abgeleitete Klasse übernehmen und so verwenden wills, als wären sie dort deklariert. Aus diesem Grund haben die Autoren von C++ das Schüsselwort protected erfunden.

In unserem Beispielprogramm finden wir dieses Schlüsselwort in Zeile 6, womit alle Daten der Klasse Vehikel in allen abgeleiteten Klassen zur Verfügung stehen, nicht jedoch außerhalb der Basisklasse oder einer der abgeleiteten Klassen. Wie wir schon früher festgestellt haben, sind alle Daten am Beginn einer Klasse automatisch private, wenn wir nichts angeben.

Die Variablen Raeder und Gewicht sind in der Methode mit dem Namen Initialisiere() in den Zeilen 83 bis 88 verfügbar, als wären sie als Teil der Klasse Auto selbst deklariert worden. Wir können sie verwenden, da wir sie in der Basisklasse als protected deklariert haben. Natürlich wären sie hier auch verfügbar, wenn wir sie als public deklariert hätten, dann wären sie aber auch außerhalb der beiden Klassen verfügbar und wir würden allen Zugriffsschutz verlieren. Selbstredend sind die beiden Variablen in der Basisklasse in den Zeilen 77 und 78 auch verfügbar. Jetzt können wir die Regeln für die drei Arten des Zugriffes auf Variablen und Methoden aufstellen.

Einführung in C++ bringt Dich in Partnerschaft mit Amazon.de von Null auf Programmieren in ein paar Klicks.

Zum Beispiel Schützen und Codieren:

C++. Der Einstieg
Ein bewährtes Buch auf halben Wegs aktuellem Stand: Arnold Willemers "C++. Der Einstieg" eignet sich tatsächlich zum Einstieg ins Programmieren mit C++ und erklärt klar strukturiert mit, ganz wichtig, allerhand Beispielen alles Wichtige.
›› Mehr C++-Bücher

Diese drei Arten des Zugriffes können auch in Strukturen verwendet werden. Der einzige Unterschied besteht darin, daß in einer Struktur alles automatisch public ist, bis wir etwas anderes festlegen.

Was sind private Daten?

Beispielprogramm: VERERB2.CPP

Im Beispielprogramm VERERB2.CPP sind die Daten der Basisklasse automatisch als private deklariert, da wir Zeile 6 auskommentiert haben. In diesem Programm sind diese Daten also in abgeleiteten Klassen nicht verfügbar. Die einzige Möglichkeit, diese Daten zu verwenden, stellen dann die Methoden der Basisklasse dar, was jetzt auch für abgeleitete Klassen gilt.

Es mutet ein wenig eigenartig an, Methoden aufrufen zu müssen, um auf Daten zugreifen zu können, die eigentlich Teil der abgeleiteten Klasse sind, aber C++ ist nun einmal so definiert. Das heißt, daß Du bei jeder Klasse ein wenig darüber nachdenken solltest, wie sie verwendet wird. Wenn Du glaubst, daß jemand eine Klasse von der Deinen ableiten wird, solltest Du die Daten als protected deklarieren, damit sie in der neuen Klasse einfach verwendet werden können. Die Zeilen 86 und 87 unseres Programmes sind jetzt nicht mehr erlaubt, da die Daten nicht sichtbar sind, also übernimmt Zeile 88 die Arbeit der beiden anderen, indem sie eine public Methode der Basisklasse aufruft. Auch Zeile 104 wurde aufgrund der versteckten Daten geändert. Kompiliere das Programm und führe es aus.

Versteckte Methoden

Beispielprogramm: VERERB3.CPP

Auch das Beispielprogramm VERERB3.CPP ist eine Wiederholung des ersten Programmes in diesem Kapitel mit einigen wenigen geringfügigen Änderungen.

Die abgeleiteten Klassen mit den Namen Auto und Laster haben das Schlüsselwort public nicht mehr vor dem Namen der Basisklasse in der ersten Zeile der jeweiligen Klassendeklaration. Wenn das Schlüsselwort public vor dem Namen der Basisklasse steht, erlaubt es, alle Methoden der Basisklasse in der abgeleiteten Klasse mit denselben Sicherheitseinschränkungen zu verwenden wie in der Basisklasse. Deshalb konnten wir auch im letzten Programm die Methoden, die als Teil der Basisklasse definiert waren, im Hauptprogramm aufrufen, obwohl wir wir mit einem Objekt einer der abgeleiteten Klassen gearbeitet haben.

In diesem Programm erben wir alle Elemente der Basisklasse als private, da vor dem Namen der Basisklasse das Schlüsselwort private steht. Deshalb sind sie außerhalb der abgeleiteten Klasse nicht verfügbar. Alle Elemente, die geerbt werden, fallen also unter zwei Zugriffsbeschränkungen, die Definitionen in der Basisklasse und die Einschränkungen bei der Ableitung. Es gilt jeweils die restriktivere der beiden. Das legt fest, wie die Elemente außerhalb der abgeleiteten Klasse verfügbar sind.

Alle Elemente werden in die abgeleitete Klasse mit denselben Zugriffsbeschränkungen übernommen, denen sie auch in der Basisklasse unterlegen sind, was ihre Sichtbarkein innerhalb der abgeleiteten Klasse selbst betrifft. In der Basisklasse verwenden wir jetzt wieder protected anstelle von private, deshalb sind die Elementvariablen innerhalb der abgeleiteten Klasse verfügbar.

In diesem Programm sind nur jene Methoden für Objekte der Klasse Auto verfügbar, die wir als Teil der Klasse selbst definiert haben. Deshalb können wir mit Objekten der Klasse Auto nur die Methoden mit den Namen Initialisiere() und Passagiere() verwenden.

Einführung in C++ bringt Dich in Partnerschaft mit Amazon.de von Null auf Programmieren in ein paar Klicks.

Zum Beispiel ent-decken:

Schrödinger programmiert C++: Jetzt mit C++14 und Syntaxhighlighting
Das beste Programmierlernbuch — egal in welcher Sprache? Kann gut sein. Statt trocken ist Dieter Bärs Meisterstück lehrreich, statt mühsam beispielhaft beispielbehaftet, statt Nachschlagewerk (das ist es wirklich nicht) Nur-noch-ein-Bissi-Weitermachbuch und statt unverständlich sinnvoll das Verstehen (statt dem Memorisiern) fördernd erklärend.
›› Mehr C++-Bücher

Wenn wir ein Objekt der Klasse Auto deklarieren, enthält es der Definition von C++ gemäß drei Variablen, und zwar die eine von seiner Klasse definierte mit dem Namen Passagieranzahl und jene zwei, die Teil der Basisklasse sind, Raeder und Gewicht. Aufgrund des Schlüsselwortes protected in der Basisklasse können wir in den Methoden der abgeleiteten Klasse alle direkt verwenden. Die Variablen sind Teil eines Objektes der Klasse Auto, wenn wir es deklarieren und werden als solche gespeichert.

Einige der Bildschirmausgaben des Hauptprogrammes haben wir auskommentiert, da sie nicht mehr gültig oder sinnvoll sind. Die Zeilen 57 bis 59 mußten wir auskommentieren, da die Methoden HoleGewicht() und Radlast() nicht als Elemente der Klasse Auto verfügbar sind. Wir verwenden private bei der Vererbung. Initialisiere() ist immer noch verfügbar, es handelt sich aber um die Methode, die wir als Teil der Klasse Auto selbst definieren, nicht jene aus der Klasse Vehikel.

Wir verwenden die Laster-Klasse in C++

Wenn wir uns nun ansehen, wie die Klasse Laster im Hauptprogramm verwendet wird, sehen wir, daß die Zeilen 63 und 65 aus obigem Grund auskommentiert wurden. Die Zeilen 66 und 67 allerdings haben wir aus einem anderen Grund auskommentiert. Zwar ist die Methode mit dem Namen Effizienz() verfügbar und kann als Element der Klasse Laster aufgerufen werden, wir können sie aber doch nicht verwenden, da keine Möglichkeit besteht, die Variablen Raeder und Gewicht des Objektes der Klasse Laster zu initialisieren. Wir können das Gewicht des Laster auslesen, wie wir es in Zeile 102 tun, aber da wir die Variable nicht initialisieren können, ist das Ergebnis bedeutungslos und wir haben die Zeilen 66 und 67 auskommentiert.

Private Vererbung ist der Verwendung eines eingebetteten Objektes sehr ähnlich und wird praktisch nicht verwendet. Bis Du sehr viel Erfahrung mit C++ und objektorientiertem Programmieren überhaupt gesammelt hast, solltest Du ausschließlich public bei der Vererbung verwenden. Es gibt wahrscheinlich keinen guten Grund, private oder protected überhaupt jemals anzuwenden. Vermutlich existieren sie nur, damit die Sprache auch komplett ist.

Kompiliere das Programm und führe es aus. (Amen.) Du solltest einige der auskommentierten Zeilen aus-kommentieren (d.h. die Kommentare entfernen), um zu sehen, mit welchen Fehlern sich der Compiler meldet.

Alle Daten initialisieren in C++

Beispielprogramm: VERERB4.CPP

Beim Durchsehen des Beispielprogrammes VERERB4.CPP wirst Du feststellen, daß wir das Initialisierungsproblem des letzten Kapitels beiseite geschafft haben. Wir haben auch jeder Klasse Standardkonstruktoren hinzugefügt, wir können also studieren, wie diese im Zusammenhang mit Vererbung verwendet werden. Außerdem sind wir bei der Vererbung zu public zurückgekehrt.

Beim Erzeugen eines Objektes der Basisklasse Vehikel haben wir kein Problem, da Vererbung hier keine Rolle spielt. Der Konstruktor der Basisklasse funktioniert genauso wie es alle Konstruktoren bisher getan haben. Bei der Erzeugung von unserem Hochrad in Zeile 47 verwenden wir den Standardkonstruktor und das Objekt wird mit den Werten des Konstruktors initialisiert. Die Zeile 49 haben wir auskommentiert, da wir keinen Initialisierungscode für das Objekt mehr brauchen.

Etwas anders stellt sich die Situation dar, wenn wir ein Objekt einer der abgeleiteten Klassen deklarieren, wie in Zeile 57 den Sedan. Wir müssen nicht nur einen Konstruktor für die abgeleitete Klasse aufrufen, sondern haben uns auch darum zu kümmern, wie wir den Konstruktor der Basisklasse aufrufen können. Das ist aber eigentlich kein Problem, da der Compiler automatisch den Standardkonstruktor der Basisklasse aufruft, solange wir nicht explizit einen (anderen) Konstruktor für die Basisklasse aufrufen. Im nächsten Beispielprogramm wollen wir gerade das tun, jetzt aber lassen wir es beim Standardkonstruktor für die Basisklasse, der automatisch aufgerufen wird, bewenden.

Reihenfolge der Konstruktion

Das nächste Problem, das sich uns stellt, ist das der Reihenfolge der Konstruktion. Die Antwort darauf merkt man sich relativ leicht: "C++ Klassen ehren ihre Eltern, indem sie deren Konstruktor vor ihren eigenen aufrufen". Der Konstruktor der Basisklasse wird vor dem der abgeleiteten Klasse aufgerufen. Das macht Sinn, da es sicherstellt, daß die Basisklasse fertig konstruiert ist, wenn der Konstruktor für die abgeleitete Klasse abgearbeitet wird. Das erlaubt Dir, einige der Daten der Basisklasse während der Konstruktion der abgeleiteten Klasse schon zu verwenden. In unserem Fall wird der Teil von Sedan, der ein Vehikel ist, zuerst konstruiert, dann werden die lokalen Elemente des Objektes Sedan konstruiert, schlußendlich sind alle Elementvariablen initialisiert. Deshalb können wir die Methode Initialisiere() in Zeile 59 auskommentieren. Wir benötigen sie nicht mehr.

Auch das Objekt Sattelschlepper wird in Zeile 66 in derselben Weise konstruiert. Der Konstruktor für die Basisklasse wird abgearbeitet, dann der Konstruktor für die abgeleitete Klasse. Jetzt ist das Objekt komplett definiert und wir können es mit den Standardwerten in allen Elementvariablen verwenden. Die Zeilen 68 und 69 brauchen wir also nicht mehr.

Der Rest des Programmes sollte, die Reihenfolge bei der Abarbeitung der Destruktoren ausgenommen, keine Probleme aufwerfen.

Wie werden die Destruktoren abgearbeitet?

Wenn die Objekt ihre Gültigkeitsbereiche verlassen, müssen auch ihre Destruktoren abgearbeitet werden und da wir keine definiert haben, werden die Standarddestruktoren verwendet. Auch hier ist das Löschen des Objektes der Basisklasse, Hochrad, kein Problem. Der Destruktor wird abgearbeitet und das Objekt ist nicht mehr. Das Objekt Sedan allerdings muß schon zwei Destruktoren abarbeiten, um alle seine Teile, den einen der Basisklasse und den anderen der abgeleiteten Klasse, zu zerstören. Es sollte Dich nicht zu sehr wundernehmen, daß die Destruktoren für dieses Objekt in umgekehrter Reihenfolge zu den Konstruktoren abgearbeitet werden. Der Destruktor der abgeleiteten Klasse wird zuerst ausgeführt, dann der Destruktor für die Basisklasse und das Objekt damit zerstört.

Bedenke: wann immer ein Objekt definiert oder erzeugt wird, muß für jeden seiner Teile ein Konstruktor ausgeführt werden. Genauso muß für jeden Teil ein Destruktor ausgeführt werden, wenn das Objekt seinen Gültigkeitsbereich verläßt.

Nach Deinem eingehenden Studium solltest Du dieses Programm kompilieren und ausführen.

Vererbung, wenn wir Konstruktoren verwenden

Beispielprogramm: VERERB5.CPP

VERERB5.CPP ist eine weitere Variation des Themas, jetzt mit Konstruktoren, die mehr sind als die bloßen Standardkonstruktoren. Jede der Klassen hat ihren eigenen Konstruktor. Der zusätzliche Konstruktor der Klasse Vehikel in den Zeilen 12 bis 14 ist nichts Besonderes, so etwas wie all die anderen Konstruktoren, die wir in dieser Einführung schon kennengelernt haben. Wir verwenden ihn in Zeile 59 des Hauptprogrammes, wo wir das Objekt Hochrad mit zwei Werten definieren.

Der Konstruktor für die Klasse Auto ist ein bißchen anders, da wir drei Variablen übernehmen. Einer der Werte, Leute, wird in der abgeleiteten Klasse selbst verwendet, um die Elementvariable mit dem Namen Passagieranzahl zu initialisieren. Die anderen beiden Werte allerdings müssen wir irgendwie an die Basisklasse übergeben, um die Werte von Raeder und Gewicht zu initialisieren. Das erreichen wir mit einer Elementinitialisierung, wie wir in diesem Konstruktor zeigen. Der Doppelpunkt am Ende der Zeile 28 bedeutet, daß eine Liste von Elementinitialisierungen folgt. Alles, was zwischen dem Doppelpunkt und der offenen geschwungenen Klammer des Konstruktors folgt, sind Elementinitialisierungen. Die erste passiert in Zeile 29 und sieht aus wie ein Konstruktoraufruf an die Klasse Vehikel, der zwei Parameter verlangt. Genau das ist sie auch und ruft den Konstruktor der Klasse Vehikel auf, um diesen Teil des Objektes Seden (als Beispiel) zu initialisieren. So können wir kontrollieren, welcher Konstruktor der Basisklasse aufgerufen wird, wenn wir ein Objekt der abgeleiteten Klasse erzeugen.

Die nächste Elementinitialisierung in Zeile 30 funktioniert in etwa wie ein Konstruktor für eine einzelne Variable. Indem wir den Namen der Variable angeben und in Klammern einen Wert des korrekten Typs wird der Variable dieser Wert zugewiesen obwohl die Variable keine Klasse, sondern ein einfacher vordefinierter Typ ist. Diese Technik kann verwendet werden, um alle Elemente der abgeleiteten Klasse oder Teile davon zu initialisieren. Sind alle Elementinitialisierungen durchgeführt, wird der Code in den geschwungenen Klammern ausgeführt. In diesem Fall befindet sich dort kein Code. Wäre dort jedoch einer, wäre er genauso geschrieben, wie dies für alle Konstruktoren gilt.

Wie sieht es mit der Reihenfolge der Ausführung aus?

Es mag eigenartig erscheinen, aber die Elemente der Elementinitialisierungsliste (...) werden nicht in der Reihenfolge abgearbeitet, in der sie aufgeführt sind. Zuerst werden die Konstruktoren für die beerbte Klasse ausgeführt, in der Reihenfolge ihrer Deklaration im Klassenkopf. Bei der Verwendung von Vielfachvererbung können mehrere Klassen in der Kopfzeile erscheinen, in diesem Programm verwenden wir aber nur eine. Dann werden die Elementvariablen initialisiert, aber nicht in der Reihenfolge, in der sie in der Liste erscheinen, sondern in der Reihenfolge ihrer Deklaration in der Klasse. Schließlich wird der Code des Konstruktors selbst ausgeführt, sofern ein solcher Code existiert.

Es gibt einen guten Grund für diese befremdend anmutende Ordnung. Die Destruktoren müssen in umgekehrter Reihenfolge der Konstruktoren aufgerufen werden, wenn aber zwei Konstruktoren mit unterschiedlicher Reihenfolge der Konstruktion definiert sind, welcher soll dann die Reihenfolge der Destruktion bestimmen? Die korrekte Antwort ist: keiner. Das System verwendet die Ordnung der Deklaration für die Konstruktion und dreht sie für die Destruktion um.

Die Klasse Laster initialisiert zum einen die Basisklasse und zum anderen zwei Elementvariablen, Passagieranzahl und Ladung. Der Konstruktor selbst enthält keinen Code, so wie schon bei der Klasse Auto.

Wir verwenden die beiden Konstruktoren für die Klassen Auto und Laster in den Zeilen 69 und 78 für ein Objekt der Klasse Auto und eines der Klasse Laster.

Der Rest des Programmes sollte kein Problem mehr darstellen. Kompiliere dieses Programm und führe es aus, bevor Du weitergehst.

Zeiger auf ein Objekt und ein Array von Objekten

Beispielprogramm: VERERB6.CPP

Die Datei VERERB6.CPP zeigt ein Beispiel für die Verwendung eines Arrays von Objekten und eines Zeigers auf ein Objekt. In diesem Programm sind die Objekte Instanzen einer abgeleiteten Klasse und der Sinn und Zweck dieses Programmes ist, zu zeigen, daß nichts Besonderes an einer abgeleiteten Klasse ist. Eine Klasse verhält sich immer gleich, sei sie nun Basisklasse oder abgeleitete Klasse.

Diese Programm ist identisch mit dem ersten in diesem Kapitel bis wir zum Hauptprogramm kommen. Dort finden wir einen Array von drei Objekten der Klasse Auto in Zeile 53. Es ist offensichtlich, daß jede Operation, die für ein einzelnes Objekt erlaubt ist, auch für ein Objekt eines Arrays gestattet ist. Wir müssen dem System nur immer mitteilen, an welchem Objekt des Arrays wir interessiert sind, indem wir den Index des Objektes in eckigen Klammern anführen, wie wir es in den Zeilen 58 bis 64 tun. Was hier geschieht, sollte Dir mittlerweile geläufig sein, wir gehen also weiter zum nächsten interessanten Konstrukt.

In Zeile 68 deklarieren wir kein Objekt der Klasse Laster, sondern einen Zeiger auf ein Objekt der Klasse Laster. Damit wir den Zeiger verwenden können, müssen wir ihm etwas geben, auf das er zeigen kann, was wir in Zeile 70 tun, indem wir dynamisch ein Objekt erzeugen. Sobald der Zeiger auf etwas zeigt, können wir das Objekt genauso wie jedes andere auch verwenden, wir müssen nur die Zeigernotation verwenden, um auf die Methoden des Objektes zuzugreifen. Das zeigen wir in den Zeilen 76 bis 80, und auch im Beispielprogramm des Kapitel 12 dieser Einführung.

Schließlich löschen wir das Objekt in Zeile 81. Du solltest Dich mit diesem Programm befassen, bis Du das neue Material verstanden hast und das Programm dann kompilieren und ausführen.

Die neue Zeit-Klasse

Wir haben eine Serie von nicht-trivialen Klassen in Kapitel 5 mit einer Datum Klasse begonnen, es kamen eine Zeit Klasse und schließlich eine DatumNeu Klasse hinzu. Jetzt ist die Reihe an Dir, diese Serie zu erweitern. Deine Aufgabe ist es, eine Klasse ZeitNeu zu entwickeln, die von der Klasse Zeit abgeleitet ist und eine neue Elementvariable mit dem Namen SekundenHeute hinzufügt sowie eine Methode, die die Sekunden, die seit Mitternacht vergangen sind, berechnet.

Programmieraufgaben

  1. Entferne die Kommentare aus den Zeilen 57 bis 59 von VERERB3.CPP und sieh Dir an, welche Fehler der Compiler ausgibt.
  2. Erweitere jeden der Konstruktoren in VERERB4.CPP um cout Anweisungen, damit Du die Reihenfolge der Abarbeitung verfolgen kannst.

(weiter »)

Einführung in C++ bringt Dich in Partnerschaft mit Amazon.de von Null auf Programmieren in ein paar Klicks.

Zum Beispiel Vererbungslehre:

Objektorientierte Programmierung: Das umfassende Handbuch. Lernen Sie die Prinzipien guter Objektorientierung.
Ungefähr alles nicht nur, das man wissen muss, sondern auch, das man wissen kann, in einem Buch. Dabei ist "Objektorientierte Programmierung" nicht unpraktisch und langweilig, nein: voll mit Beispielen und vor allem verständlichen Erklärungen, macht es einen interessiert — und mit brauchbarer objektorientierung zur besseren Programmiererin.
›› Mehr Softwareentwicklung-Bücher

[ sich ]