C++ Vererbung Abstrakte Klasse als Basisklasse

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
MiCsoft
Beiträge: 18
Registriert: So Nov 08, 2020 8:18 pm

C++ Vererbung Abstrakte Klasse als Basisklasse

Beitrag von MiCsoft » Di Dez 01, 2020 8:51 pm

Guten Tag zusammen,
ich verstehe an einer Aufgabe irgendwie nicht so ganz wie das Funktionieren soll.

Hier mal die Aufgabe:
Fahrzeuge. Diese Oberklasse soll abstrakt sein.
a. Eigenschaften: i. Bezeichnung ii. Verfügbar (ja/nein)
b. Methoden:
i. Einlesen (Eigenschaften beim Benutzer abfragen)
ii. Ausgabe (Eigenschaften am Bildschirm ausgeben)
iii. FahrzeugVerleihen (=>nicht mehr verfügbar!)
iv. FahrzeugZurücknehmen (=>wieder verfügbar!)

PKW (zusätzlich zu Fahrzeuge)
a. Eigenschaften i. KW ii. Höchstgeschwindigkeit iii. Sitzplätze
Die Fahrzeug.h habe ich so gemacht:

Code: Alles auswählen

#include <string>
using namespace std;

class Fahrzeug {
protected:
	bool available; //verfügbar
	string name;
public:
	virtual ~Fahrzeug();
	void virtual einlesen() = 0;
	void virtual ausgabe() = 0;
	void virtual fahrzeugVerleihen(bool b) = 0;
	void virtual fahrzeugZur(bool b) = 0;

};
Die PKW.h so:

Code: Alles auswählen

#include "Fahrzeuge.h"

class PKW : public Fahrzeug {
private:
	unsigned int kw;
	double speed; //höchstgeschwindigkeit
	unsigned int size; //Sitzplätze

public:
	//Konstruktor anschauen so:
	// PKW(Name, available, KW, Speed, Size)
	PKW();
	~PKW();
	void einlesen() override;
	void ausgabe() override;
	void fahrzeugVerleihen(bool b) override;
	void fahrzeugZur(bool b) override;
};
Nun meine Frage, die Klasse Fahrzeug braucht doch einen Konstruktor damit ich den string name doch initialisiert bekomme oder?
Dann noch eine Frage sollte man den Konstruktor dann protected machen?

MiCsoft
Beiträge: 18
Registriert: So Nov 08, 2020 8:18 pm

Re: C++ Vererbung Abstrakte Klasse als Basisklasse

Beitrag von MiCsoft » Di Dez 01, 2020 9:33 pm

Ich hab das ganze etwas geändert:
Fahrzeug.cpp

Code: Alles auswählen

#include "Fahrzeuge.h"

Fahrzeug::Fahrzeug() {
	name = "";
	available = false;
}

Fahrzeug::~Fahrzeug() {
	name.clear();
}
Fahrzeuge.h

Code: Alles auswählen

#include <string>
#ifndef FAHRZEUGE_H_
#define FAHRZEUGE_H_
using namespace std;

class Fahrzeug {
protected:
	bool available; //verfügbar
	string name;
public:
	Fahrzeug();
	virtual ~Fahrzeug();
	Fahrzeug(const Fahrzeug &other) = delete;
	Fahrzeug &operator=(const Fahrzeug &other) = delete;
	void virtual einlesen() = 0;
	void virtual ausgabe() = 0;
	void virtual fahrzeugVerleihen() = 0;
	void virtual fahrzeugZur() = 0;

};
#endif /* FAHRZEUGE_H_ */
PKW.h

Code: Alles auswählen

#ifndef PKW_H_
#define PKW_H_

#include "Fahrzeuge.h"

class PKW : public Fahrzeug {
private:
	unsigned int kw;
	double speed; //höchstgeschwindigkeit
	unsigned int size; //Sitzplätze

public:
	//Konstruktor anschauen so:
	// PKW(Name, available, KW, Speed, Size)
	PKW();
	~PKW();
	void einlesen() override;
	void ausgabe() override;
	void fahrzeugVerleihen() override;
	void fahrzeugZur() override;
};
#endif /* PKW_H_ */
PKW.cpp

Code: Alles auswählen

#include "PKW.h"
#include <iostream>

void PKW::einlesen() {
	cout << "Bitte Name des PKW eingeben: " << endl;
	cin >> name;
}

void PKW::ausgabe() {
	cout << "Der PKW heißt: " << name << endl;
}

void PKW::fahrzeugVerleihen() {
	available = false;
}

PKW::PKW() {
}

PKW::~PKW() {
	cout << "destruktor" << endl;
}

void PKW::fahrzeugZur() {
	available = true;
}
Wie müsste der PKW Konstruktor und Destruktor aussehen?
Wie lösche ich denn einen String in C++? Sprich wie schreibe ich dann den Destruktor in Fahrzeuge?

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: C++ Vererbung Abstrakte Klasse als Basisklasse

Beitrag von nufan » Mi Dez 02, 2020 7:49 am

Hallo MiCsoft! :)

Ich fange mal bei deinen konkreten Fragen an:
MiCsoft hat geschrieben:
Di Dez 01, 2020 9:33 pm
Wie lösche ich denn einen String in C++? Sprich wie schreibe ich dann den Destruktor in Fahrzeuge?
Du meinst wie du den Speicher des Namens wieder freigibst? Das musst du gar nicht tun, das übernimmt der Destruktor von std::string schon für dich. Der Destruktor deiner Member-Variablen wird automatisch aufgerufen, sobald das beinhaltende Objekt zerstört wird.
MiCsoft hat geschrieben:
Di Dez 01, 2020 9:33 pm
Wie müsste der PKW Konstruktor und Destruktor aussehen?
Der PKW-Konstruktor sollte alle Werte als Parameter bekommen, die notwendig sind, um ein PKW-Objekt gültig zu initialisieren. Werte die von der Elternklasse "Fahrzeug" kommen, kannst du direkt an den Konstruktor der Elternklasse weitergeben:
https://www.proggen.org/doku.php?id=cpp:inheritance:def

Einen Destruktor brauchst du, wenn du Ressourcen des Objekts wieder freigeben musst. Das heißt z.B. dass du angeforderten Speicher wieder freigibst oder offene Dateien schließt. In dem von dir gezeigten Beispiel hast du nur einfache Variablen, du brauchst also keinen Destruktor.


Soweit zu deinen Fragen, ich habe auch noch ein paar Anmerkungen:
Mir ist nicht klar, wieso "fahrzeugVerleihen()" und "fahrzeugZur()" abstrakt sein sollten. Gibt es noch andere Ableitungen, die diese Funktionen anders implementieren?
Warum verbietest du den Copy-Constructor sowie die Zuweisung von "Fahrzeug"?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: C++ Vererbung Abstrakte Klasse als Basisklasse

Beitrag von Xin » Mi Dez 02, 2020 9:55 am

Vorweg: Deine Implementation ist korrekt. Also wenn ich Dir das als Aufgabe geben würde, wäre Deine Implementierung absolut in Ordnung. Ich geb Dir lediglich ein paar Hinweise mit.

Wenn Du den Default-Konstruktor von Fahrzeuge rufst, ruft dieser den Default-Konstruktor von String. Und der Default-Konstruktor von String erzeugt einen leeren String. name = "" ändert daran nichts mehr. Das können wir also weglassen:

Code: Alles auswählen

Fahrzeug::Fahrzeug() {
	available = false;
}
Bei dem Bool passiert nix, aber wenn es ein echtes Objekt wäre, würde erst der Default-Konstruktor des Datentyps gerufen, anschließend wird das gerade erzeugte Objekt mit "false" überschrieben. Vor dem Konstruktor läuft die Initialisierungsliste, hier wird also das Objekt direkt mit dem übergebenen Werten konstruiert:

Code: Alles auswählen

Fahrzeug::Fahrzeug() 
  : available( false )
{
}
Da es sich um Primitiv handelt, kann man das auch in die Header-Datei packen:

Code: Alles auswählen

class Fahrzeug {
protected:
	bool available = false; //verfügbar, aber im Standardfall nicht verfügbar
	string name;
	
public:
	Fahrzeug() = default;   // bau Dir Deinen Default-Konstruktor doch selbst.
	virtual ~Fahrzeug();
	
Damit kann ich mir das Schreiben des Konstruktor komplett sparen. Wichtigster Grund ist nicht, dass man die "Arbeit" für die paar Zeilen spart, sondern dass man Code, der nicht geschrieben wurde, die nächsten Jahrzehnte auch nicht warten muss.

Prinzipiell günge das auch mit dem Destruktor, aber diverse Compiler nutzen die Lage des virtuellen Konstruktors für etwas anderes (die Positionierung der Virtual Table), hier gilt derzeit: So implementieren, wie Du es getan hast.
MiCsoft hat geschrieben:
Di Dez 01, 2020 9:33 pm
Wie müsste der PKW Konstruktor und Destruktor aussehen?
So wie Du ihn implementiert hast, passt das.
MiCsoft hat geschrieben:
Di Dez 01, 2020 9:33 pm
Wie lösche ich denn einen String in C++? Sprich wie schreibe ich dann den Destruktor in Fahrzeuge?
Siehe Nufan. :-)

Aber ich habe noch eine Frage: Beim Verleihen oder Zurückgeben des Fahrzeugs möchte die Methode ein Bool haben. Warum?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

MiCsoft
Beiträge: 18
Registriert: So Nov 08, 2020 8:18 pm

Re: C++ Vererbung Abstrakte Klasse als Basisklasse

Beitrag von MiCsoft » Di Dez 08, 2020 3:41 pm

Vielen Dank an euch zwei =)
Hab es hin bekommen :-)

Aber ich habe noch eine Frage: Beim Verleihen oder Zurückgeben des Fahrzeugs möchte die Methode ein Bool haben. Warum?
Das war eine gute Frage =D keine Ahnung was ich an dem Tag dort gedacht habe.

Man brauch ja nur das Datenelement der Klasse in der Verleihen Methode auf true oder false zu setzen =)

Hab schon ein paar mehr Ideen gehabt und kleine Mini Klassen geschrieben hat bisher immer gut funktioniert. Man braucht eben immer etwas Übung.

Antworten