Sie haben nun gelernt, was Smart Pointer sind und wie sie angewendet werden können. Im Folgenden können Sie das Gelernte mit einigen praktischen Aufgaben und Verständnisfragen überprüfen.
In diesem Aufgabenteil werden Sie das bereits bekannte
Train-Beispiel um die Klasse Station
erweitern. Dem Namen entsprechend soll die neue Klasse die Bahnhöfe
simulieren, an denen unsere Züge halten werden.
Legen Sie die Klasse Station an. Sie soll den Namen des
Bahnhofs in der Variable p_sName speichern und einen
Pointer p_pDestination besitzen, in dem der Zielbahnhof
gespeichert werden soll. Überlegen Sie, welcher der Ihnen nun bekannten
Smart Pointer-Arten am besten dafür geeignet ist.
Im nächsten Schritt sollen einige nützliche Funktionen angelegt
werden. Zunächst müssen Sie einen Konstruktor und eine
getName()-Funktion erstellen.
Jetzt soll der Zielbahnhof p_pDestination in der
Funktion vSetDestination() gesetzt werden. Dazu übergeben
Sie einen Pointer, der diesen beinhaltet. Bedenken Sie weiterhin die
Wahl des Smart Pointers! Zusätzlich muss man auch den Inhalt von
p_pDestination auch wieder auslesen können, deswegen müssen
Sie auch eine Funktion getDestination() implementieren.
Zum Schluss fügen Sie Ihre in vorherigen Aufgabenteilen geschriebenen
Klassen Train, sowie deren Unterklassen
PassengerTrainund FreightTrain an passender
Stelle ein und führen alle Zellen (auch die Test-Zelle!) nacheinander
aus, um die Richtigkeit Ihrer Lösungen zu überprüfen.
#include <iostream>
#include <string>
#include <memory>
//hier: Station.h implementieren
//Station.cpp
//hier: Konstruktor für Station
//hier: Funktion Station::getName()
//hier: Funktion Station::getDestination()
//hier: Funktion Station::vSetDestination()
//hier: Train.h einfügen
//Train.cpp
//hier: Destruktor einfügen
//hier: Train::vGoTo() einfügen
//hier: Train::vPrintProperties() einfügen
//hier: PassengerTrain.h einfügen
//PassengerTrain.cpp
//hier: Konstruktor einfügen
//hier: Funktion PassengerTrain::vPrintProperties() einfügen
//hier: Funktion PassengerTrain::fStation() einfügen
//hier: FreightTrain.h einfügen
//FreightTrain.cpp
//hier: Konstruktor einfügen
//hier: Funktion FreightTrain::vPrintProperties() einfügen
//hier: Funktion FreightTrain::vLoadCharge() einfügen
#define OPERATOR operator<< //Diese Zeile kann in jeder IDE weggelassen werden, sie ist nur für Jupyter notwendig
std::ostream & OPERATOR(std::ostream& out, const Train& train)
{
train.vPrintProperties(out);
return out;
}
#undef OPERATOR //Diese Zeile kann in jeder IDE weggelassen werden, sie ist nur für Jupyter notwendig
// Test
std::unique_ptr<PassengerTrain> aTrain;
aTrain = std::make_unique<PassengerTrain>();
auto bTrain = std::make_unique<FreightTrain>(2, "tons of wood");
std::cout << std::endl << "Eigenschaften 'aTrain':" << std::endl;
std::cout << *aTrain;
std::cout << std::endl << "Eigenschaften 'bTrain':" << std::endl;
std::cout << *bTrain << std::endl;
auto berlin = std::make_shared<Station>("Berlin");
auto hamburg = std::make_shared<Station>("Hamburg");
auto frankfurt = std::make_shared<Station>("Frankfurt");
auto koeln = std::make_shared<Station>("Köln");
auto muenchen = std::make_shared<Station>("München");
//rudimentäre Linie aufbauen (die bekannte Ringbahn Hamburg-Hamburg)
hamburg->vSetDestination(koeln);
koeln->vSetDestination(frankfurt);
frankfurt->vSetDestination(berlin);
berlin->vSetDestination(hamburg);
std::cout << "Guten Tag meine Damen und Herren, herzlich willkommen im Zug der Deutschen Bahn von Hamburg nach Hamburg über Köln Hbf, Frankfurt Hbf und Berlin Gesundbrunnen!" << std::endl;
std::cout << std::endl;
std::cout << "Sehr geehrte Fahrgäste, in wenigen Minuten erreichen wir Köln Hauptbahnhof. Wir verabschieden uns von allen Fahrgästen, die dort aus- und umsteigen und wünschen eine angenehme Weiterreise. Bitte denken Sie beim Aussteigen daran, Ihre persönlichen Wertgegenstände mitzunehmen. Vielen Dank!" << std::endl;
aTrain->vGoTo(koeln);
std::cout << std::endl;
aTrain->vGoTo(muenchen); //Sollte nicht funktionieren, nicht Teil der Ringbahn
std::cout << std::endl;
std::cout << "Sehr geehrte Fahrgäste, in wenigen Minuten erreichen wir Frankfurt Hauptbahnhof. Wir verabschieden uns von allen Fahrgästen, die dort aus- und umsteigen und wünschen eine angenehme Weiterreise. Bitte denken Sie beim Aussteigen daran, Ihre persönlichen Wertgegenstände mitzunehmen. Vielen Dank!" << std::endl;
aTrain->vGoTo(frankfurt);
std::cout << std::endl;
std::cout << "Sehr geehrte Fahrgäste, in wenigen Minuten erreichen wir Berlin Gesundbrunnen. Wir verabschieden uns von allen Fahrgästen, die dort aus- und umsteigen und wünschen eine angenehme Weiterreise. Bitte denken Sie beim Aussteigen daran, Ihre persönlichen Wertgegenstände mitzunehmen. Vielen Dank!" << std::endl;
aTrain->vGoTo(berlin);
std::cout << std::endl;
std::cout << "Sehr geehrte Fahrgäste, in wenigen Minuten erreichen wir Hamburg Hauptbahnhof. Unsere Fahrt endet dort, wir bitten alle Fahrgäste, auszusteigen." << std::endl;
aTrain->vGoTo(hamburg);
std::cout << "Wir bedanken uns für Ihre Reise mit der Deutschen Bahn." << std::endl;
Eigenschaften 'aTrain':
ID: 6
momentane Verspaetung: 0 Minuten
Anzahl Passagiere: 0
Eigenschaften 'bTrain':
ID: 7
momentane Verspaetung: 0 Minuten
Ladung: 2 tons of wood
Guten Tag meine Damen und Herren, herzlich willkommen im Zug der Deutschen Bahn von Hamburg nach Hamburg über Köln Hbf, Frankfurt Hbf und Berlin Gesundbrunnen!
Sehr geehrte Fahrgäste, in wenigen Minuten erreichen wir Köln Hauptbahnhof. Wir verabschieden uns von allen Fahrgästen, die dort aus- und umsteigen und wünschen eine angenehme Weiterreise. Bitte denken Sie beim Aussteigen daran, Ihre persönlichen Wertgegenstände mitzunehmen. Vielen Dank!
Zug ist nach Köln gefahren.
Der Zug kann nicht nach München fahren: Es gibt keine Verbindung.
Sehr geehrte Fahrgäste, in wenigen Minuten erreichen wir Frankfurt Hauptbahnhof. Wir verabschieden uns von allen Fahrgästen, die dort aus- und umsteigen und wünschen eine angenehme Weiterreise. Bitte denken Sie beim Aussteigen daran, Ihre persönlichen Wertgegenstände mitzunehmen. Vielen Dank!
Zug ist nach Frankfurt gefahren.
Sehr geehrte Fahrgäste, in wenigen Minuten erreichen wir Berlin Gesundbrunnen. Wir verabschieden uns von allen Fahrgästen, die dort aus- und umsteigen und wünschen eine angenehme Weiterreise. Bitte denken Sie beim Aussteigen daran, Ihre persönlichen Wertgegenstände mitzunehmen. Vielen Dank!
Zug ist nach Berlin gefahren.
Sehr geehrte Fahrgäste, in wenigen Minuten erreichen wir Hamburg Hauptbahnhof. Unsere Fahrt endet dort, wir bitten alle Fahrgäste, auszusteigen.
Zug ist nach Hamburg gefahren.
Wir bedanken uns für Ihre Reise mit der Deutschen Bahn.
Hier finden Sie eine mögliche Lösung zu den Aufgaben. Bitte beachten Sie, dass es mehrere Möglichkeiten gibt, die Aufgaben zu lösen, hier wird lediglich eine Variante aufgezeigt. Solange Ihre Implementierung funktioniert wie gefordert, ist sie wahrscheinlich richtig!
class Station
{
private:
std::string p_sName;
std::shared_ptr<Station> p_pDestination;
public:
Station(std::string station);
void vSetDestination(std::shared_ptr<Station> dest);
std::string getName() const;
std::shared_ptr<Station> getDestination() const;
};
Station::Station(std::string station) : p_sName(station)
{
}
std::string Station::getName() const
{
return p_sName;
}
std::shared_ptr<Station> Station::getDestination() const
{
return p_pDestination;
}
void Station::vSetDestination(std::shared_ptr<Station> dest)
{
p_pDestination = dest;
}
In diesem Teil wird es einige Aufgaben geben, die eher theoretischer
Natur sind. Sie werden Codesnippets sehen, bei denen sich Fehler
eingeschlichen haben, die Sie korrigieren sollen. Bitte führen Sie
zuerst die include-Befehle aus, damit keine Zusatzfehler
auftreten ;-).
#include <iostream>
#include <memory>
Im folgenden Abschnitt soll der Inhalt eines weak_ptr
ausgegeben werden. Allerdings funktioniert die Ausgabefunktion nicht.
Finden Sie die Fehler und testen Sie Ihre Lösung mit der unten
angegebenen Test-Funktion.
void printContent(std::weak_ptr<std::string> weak){
std::cout << "Der Inhalt des weak-Pointers ist: " << weak << std::endl;
}
{
auto test_shared = std::make_shared<std::string>("Test");
auto test_weak = test_shared;
printContent(test_weak);
}
Es soll der Inhalt eines unique_ptr-Arrays umgekehrt in
einem anderen gespeichert werden. Allerdings funktioniert das noch nicht
so ganz. Finden Sie die Fehler.
std::unique_ptr<int[]> reverseArray(std::unique_ptr<int[]> unique_array){
auto reversed_array = std::make_unique<int[]>(10);
for(int i = 0; i < 10; i++){
reversed_array[i] = 9 - unique_array[i];
}
return reversed_array;
}
{
auto unique_array = std::make_unique<int[]>(10);
for(int i = 0; i < 10; i++){
unique_array[i] = i;
}
std::cout << "Das ursprüngliche Array:" << std::endl;
for(int i = 0; i < 10; i++){
std::cout << "Stelle: " << i << " Inhalt: " << unique_array[i] << std::endl;
}
auto reversed_array = reverseArray(unique_array);
std::cout << "Das umgedrehte neue Array:" << std::endl;
for(int i = 0; i < 10; i++){
std::cout << "Stelle: " << i << " Inhalt: " << reversed_array[i] << std::endl;
}
}
Der Fehler befindet sich in der Ausgabezeile. Auf den Inhalt eines
Pointers kann nur mit entsprechender Referenzierung mit dem * -Operator
zugegriffen werden. Bei weak_ptr muss zusätzlich die
Funktion lock() genutzt werden, um den Inhalt abrufen zu
können. Richtig ist also
std::cout << "Der Inhalt des weak-Pointers ist: " << *weak.lock() << std::endl;.
unique_ptr können nicht einfach kopiert werden, da es
sonst mehr als eine Referenz auf das Objekt gibt. Deswegen
muss der move()-Befehl benutzt werden!
Richtig ist also, sowohl bei dem Aufruf von reverseArray,
als auch beim return-Statement diesen Befehl zu verwenden:
auto reversed_Array = reverseArray(move(unique_array)); und
return move(reversed_array);.