MINT lernen

Übungen: Klassen

Bauplan, Objekt, Kapselung — hier zeigst du, dass deine Klassen dicht halten, was sie versprechen.

Dein Fortschritt:
0 / 0 Aufgaben
1

Übungsaufgaben

Zehn Übungen zu Klassen, Konstruktoren, Kapselung und der Aufteilung auf .h und .cpp — von AFB I bis AFB III. Jede Übung gibt dir sofort Rückmeldung; wenn du nicht weiterkommst, helfen die gestuften Tipps.

A1
Lückentext: Fachbegriffe
AFB I

Nenne die fehlenden Fachbegriffe, indem du sie einsetzt — zwei Wörter bleiben übrig.

Wort anklicken, dann Lücke anklicken (oder umgekehrt) — mit Tab und Enter geht es genauso. Ein Klick auf eine gefüllte Lücke legt das Wort zurück.

Eine Klasse ist der ; ein nach ihm angelegtes hat eigene Attributwerte. Attribute stehen meist im Bereich , damit nur die eigenen sie ändern können — dieses Prinzip heißt . Der heißt wie die Klasse, hat keinen Rückgabetyp und setzt die Startwerte.

Der Ablenker public ist der häufigste Fehler: Öffentliche Attribute könnte jede Funktion beliebig ändern — genau das soll die Kapselung verhindern. Eine Referenz ist ein zweiter Name für eine Variable, kein Teil einer Klasse.
Ansatz: Denk an Java: Dort hast du dieselben Begriffe schon benutzt.
Weiter: Der Bereich, auf den nur die Klasse selbst zugreift, heißt private.
A2
Stimmt’s? — Klassen in C++
AFB I

Gib zu jeder Aussage an, ob sie stimmt.

Fünf Aussagen nacheinander. Eine falsche Einschätzung reicht — dann startest du die Serie mit „Neue Runde“ neu.
Aussage 1 von 5

Den void-Konstruktor kennen viele aus Versehen: Er sieht wie eine normale Methode aus, g++ lehnt ihn aber ab („return type specification for constructor invalid“).
Ansatz: Vergleiche mit Java: Was ist dort anders beim Anlegen von Objekten und beim Klassenende?
Weiter: struct und class unterscheiden sich nur im Standard-Zugriff.
A3
Zwei Zähler
AFB I
C++ · zaehler.cpp
class Zaehler {
  private:
    int stand;
  public:
    Zaehler(int start) { stand = start; }
    void klick() { stand = stand + 1; }
    int getStand() { return stand; }
};

int main() {
    Zaehler z(7);
    z.klick();
    z.klick();
    Zaehler w(z.getStand() * 2);
    w.klick();
    cout << z.getStand() + w.getStand() << endl;
    return 0;
}

Bestimme die Ausgabe.

Überlege selbst und trage das Ergebnis ein — Enter prüft direkt.
z startet bei 7 und steht nach zwei Klicks bei 9. w startet bei 9 · 2 = 18, nach einem Klick bei 19. Summe: 9 + 19 = 28. Typischer Fehler: zu denken, w.klick() erhöhe auch z — jedes Objekt hat aber sein eigenes Attribut stand.
Ansatz: Führe für jedes Objekt eine eigene Notiz mit seinem Wert von stand.
Weiter: w wird erst angelegt, nachdem z zweimal geklickt wurde.
A4
Was meint der Compiler?
AFB II

Zu einer Klasse Lampe mit dem Attribut private: int hell; und dem Konstruktor Lampe(int h) hat g++ sechs Fehlermeldungen ausgegeben. Ordne jeder Meldung die Ursache zu.

Ansatz: Suche in jeder Meldung ein Schlüsselwort: private, constructor, member, class definition …
Weiter: Lampe::Lampe() ist der Konstruktor ohne Parameter.
A5
Klasse auf zwei Dateien verteilt
AFB II

Die Klasse Thermometer ist auf thermo.h und thermo.cpp aufgeteilt; übersetzt wird mit g++ main.cpp thermo.cpp -o th. Ergänze die Lücken.

Wähle in jedem Menü den passenden Eintrag und prüfe dann alle auf einmal.
C++ · thermo.h
#ifndef THERMO_H
#define THERMO_H
class Thermometer {
  private:
    double grad;
  public:
    Thermometer(double start);
    void erwaermen(double d);
    double getGrad();
    bool frostig();

#endif
C++ · thermo.cpp
#include 
Thermometer::Thermometer(double start) { grad = start; }
void erwaermen(double d) { grad = grad + d; }
double Thermometer::getGrad() { return grad; }
 Thermometer::frostig() { return grad < 0; }
Der Rückgabetyp in der .cpp-Datei muss genau zum Prototyp im Header passen: bool frostig(); → bool Thermometer::frostig(). Typischer Fehler: Thermometer.erwaermen — der Punkt gehört zum Aufruf an einem Objekt, :: zur Definition. Eigene Header stehen in Anführungszeichen, Bibliotheks-Header in spitzen Klammern.
Ansatz: Vergleiche jede Zeile in thermo.cpp mit ihrem Prototyp im Header.
Weiter: Eine Klassendefinition endet mit }; — auch im Header.
A6
Zwei Tanks
AFB II Mix

Achtung, hier steckt auch Ganzzahldivision aus 2.1.2 drin.

C++ · tank.cpp
class Tank {
  private:
    int liter, max;
  public:
    Tank(int m) : liter(0), max(m) {}
    void tanken(int l) { liter = liter + l; if (liter > max) liter = max; }
    void fahren(int km) { liter = liter - km / 20; if (liter < 0) liter = 0; }
    int getLiter() { return liter; }
};

Tank a(40), b(50);
a.tanken(30);                  // Zeile 1
b.tanken(65);                  // Zeile 2
a.fahren(250);                 // Zeile 3
b.fahren(1010);                // Zeile 4
a.tanken(b.getLiter() + 25);   // Zeile 5

Stelle die Füllstände nach jeder Zeile in der Tabelle dar.

Fülle alle Felder aus und prüfe dann. Enter in einem Feld prüft ebenfalls.
nacha.getLiter()b.getLiter()
Zeile 1
Zeile 2
Zeile 3
Zeile 4
Zeile 5
Die Initialisierungsliste setzt liter auf 0 und max auf den Startwert. Zeile 2 kappt 65 auf 50, Zeile 3 rechnet 250 / 20 = 12 (nicht 12,5), Zeile 4 rechnet 1010 / 20 = 50 und landet bei 0, in Zeile 5 wird 18 + 25 = 43 auf das Maximum 40 gekappt. Typischer Fehler: in Zeile 3 auf 17,5 oder 17 kommen.
Ansatz: Jedes Objekt hat eigene Werte für liter und max: a darf höchstens 40, b höchstens 50 Liter haben.
Weiter: Ganzzahldivision schneidet ab: 250 / 20 = 12, 1010 / 20 = 50.
A7
C++ oder Java?
AFB II

Du kennst Klassen schon aus Java. Vergleiche und markiere alle zutreffenden Aussagen.

Mehrere Antworten sind richtig. Markiere alle zutreffenden und klicke dann auf „Prüfen“.
C++ arbeitet mit Bereichen: private: und public: gelten für alles, was danach folgt. Konstruktoren gibt es wie in Java. Typischer Fehler: Die Java-Gewohnheit new in C++ übernehmen — Lampe l = new Lampe(3); übersetzt g++ nicht.
Ansatz: Schreib dir dieselbe kleine Klasse einmal in Java und einmal in C++ auf.
Weiter: Achte auf new, das Semikolon am Ende und die Schreibweise von private.
A8
Fehlersuche: Wecker
AFB III

Der Wecker soll auf 6:45 gestellt werden und nach 30 Minuten die Stunde 7 ausgeben. Überprüfe den Code — drei Zeilen sind fehlerhaft.

In diesem Code stecken Fehler. Klicke genau die fehlerhaften Zeilen an — die richtigen musst du stehen lassen.
Die Zeilen 7 bis 9 sehen verdächtig aus, stimmen aber: 45 + 30 = 75 Minuten, 75 / 60 = 1 Stunde dazu (Ganzzahldivision), 75 % 60 = 15 Minuten Rest — also 7:15. Die drei Fehler sind klassische Umsteigerfehler von Java nach C++.
Ansatz: Prüfe den Konstruktor, das Klassenende und jeden Zugriff aus main.
Weiter: Auf private-Attribute greift man von außen nur über Methoden wie getStunde() zu.
A9
Was darf ein Konto verraten?
AFB III

Du entwirfst eine Klasse Konto für eine Mensa-Karte mit PIN. Lege für jedes Mitglied fest, wohin es gehört — manches bietet man besser gar nicht an.

Ziehe jede Karte in den passenden Korb — oder wähle sie mit Enter aus und drücke dann die Ziffer des Korbs (0 legt sie zurück).
1private
2public
3gar nicht anbieten
Attribute sind privat. Öffentlich sind nur Methoden, die die Regeln einhalten: abheben prüft die PIN und den Kontostand. Ein setKontostand würde jede Regel umgehen, und getPin verrät das Geheimnis — beide machen die Kapselung wertlos. Typischer Fehler: zu jedem Attribut automatisch Getter und Setter anlegen.
Ansatz: Frage bei jeder Methode: Könnte jemand damit die Regeln der Mensa-Karte umgehen?
Weiter: Einen Kontostand ansehen ist harmlos, ihn frei setzen nicht.
A10
Welche Zeilen übersetzt g++?
AFB III Trick
C++ · feld.cpp
struct Punkt { int x, y; };

class Feld {
    int breite;
  public:
    Feld(int b) { breite = b; }
    int getBreite() { return breite; }
};

In main stehen nacheinander: Punkt p; p.x = 3; · Feld f(5); · f.breite = 7; · Feld g; · cout << f.getBreite(); · Punkt q = {1, 2};. Beurteile jede Zeile und gib an, wie viele davon g++ fehlerfrei übersetzt.

Überlege selbst und trage das Ergebnis ein — Enter prüft direkt.
Übersetzt werden Punkt p; p.x = 3;, Feld f(5);, cout << f.getBreite(); und Punkt q = {1, 2}; — also 4. Die Falle: Über int breite; steht kein private:, trotzdem ist es privat, weil in einer class alles bis zum ersten Bereich private ist. Feld g; scheitert, weil es keinen Konstruktor ohne Parameter gibt.
Ansatz: Was gilt in einer class, bevor das erste public: kommt?
Weiter: Beim struct ist alles öffentlich. Ein Objekt ohne Startwert braucht einen Konstruktor ohne Parameter.