Klasse / Konstruktor / doppelten Aufruf verhindern.



  • Hallo,
    ich habe folgendes Verständnisproblem:

    Ich habe hier eine Art Verwaltung von Mediendaten. Soweit verstehe ich die einzelnen Schritte, aber bei Folgendem tue ich mich etwas schwer:

    ...
    Video::Video(): Medium(false) {
    	entliehen = false;	
    ...
    

    Das wird aufgerufen wenn ich mit new ein neues Video anlegen will. Video ist abgeleitet von der Basisklasse Medium.

    ...
    class Medium {
    
    	protected:	
    		int signatur;
    		string titel;
    		bool entliehen;
    
    	public:		
    		Medium();		
    		Medium(bool) { this->entliehen = false; }
    ...
    

    Lasse ich Zeile in der Header-Datei weg, wird beim Anlegen eines Videos gleichzeitig ein Medium angelegt.

    Meine Frage ist nun, was genau passiert, dass verhindert wird, dass gleichzeitig ein Medium angelegt wird?

    Im Grunde genommen wird beim Anlegen eines neuen Videos der Konstruktor** Medium(bool) aufgerufen, anstatt der Default-Konstruktor. Ist also Medium(bool) **ein Basisinitialisierer?

    :xmas1:


  • Mod

    Das ist eine Initialisierungsliste. Damit kann man bei der Konstruktion eines Objektes Parameter für dessen Basisklassen- und Memberkonstruktoren angeben.

    Das wird aufgerufen wenn ich mit new ein neues Video anlegen will.

    Ich hoffe das ist nur beispielhaft gesagt und du siehst new nicht wirklich als einzige (oder gar übliche) Art an, Objekte zu erzeugen. C++ ist nicht Java.



  • Ich hoffe das ist nur beispielhaft gesagt...

    Ich wollt nur klarmachen, wie ich zu diesem Punkt im Code kommen.

    Was passiert denn nun genau, damit nicht gleichzeitig ein Medium erstellt wird?


  • Mod

    djhaefd schrieb:

    Was passiert denn nun genau, damit nicht gleichzeitig ein Medium erstellt wird?

    Ist das eine Frage, wie das sein kann, oder eine Frage, wie man das erreichen kann?

    Wenn Video ein Medium als Member oder Basisklasse hat, dann muss ein Medium erstellt werden, wenn ein Video erstellt wird. Da führt kein Weg dran vorbei. Falls du es verhindern möchtest: Unmöglich. Falls du zu dem Eindruck gekommen sein solltest, dass dies irgendwie nicht passiert: Du irrst dich.



  • Ich habe insgesamt drei Objekte. Buch und Video sind abgeleitete Klssen der Basisklasse Medium. Wenn ich also ein Buch oder Video anlegen möchte, wird nur ein Buch oder ein Video angelegt. Lasse ich diese Zeile weg:

    Medium(bool) { this->entliehen = false; }
    

    wird zuerst ein Medium angelegt und dann ein Buch oder Video.

    Also wie man das erreichen kann, hab ich wohl schon geschafft. Aber was da genau passiert, darauf kommen ich nicht.


  • Mod

    Wenn ich also ein Buch oder Video anlegen möchte, wird nur ein Buch oder ein Video angelegt.

    Wie kommst du zu dieser Aussage? Es ist unmöglich. Deine Methodik muss fehlerhaft sein.



  • Weil ich danach die angelegten Objekte in einer Liste sehe 🙂


  • Mod

    djhaefd schrieb:

    Weil ich danach die angelegten Objekte in einer Liste sehe 🙂

    Soso. Dann ist ja alles klar. :xmas2:



  • Soso. Dann ist ja alles klar. :xmas2:

    Undzwar? Ich weiß immernoch nicht, was der Konstruktor** Medium(bool) **macht und danach der this-Zeiger...


  • Mod

    djhaefd schrieb:

    Soso. Dann ist ja alles klar. :xmas2:

    Undzwar?

    Na, nichts ist klar. Du machst irgendetwas geheimnisvolles mit Listen, was du dir nicht erklären kannst, aber du magst uns auch nicht sagen, was du überhaupt tust, was passiert, noch was du erwartest.

    "Herr Doktor, mir geht es nicht gut."
    "Was fehlt Ihnen denn?"
    "Das sollen Sie mir sagen!"
    😕



  • Also nochmal ganz detailliert:
    Ich habe eine Medienverwaltung, bei der ich
    - neue Objekte //Buch oder Video oder Medium// anlegen kann,
    - angelegte Objekte anzeigen lassen kann
    - Objekte ausleihen und zurückgeben kann.

    Dazu gibt es drei Klassen. Klasse Buch und Video sind von der Basisklasse Medium:

    class Medium {
    
    	protected:	
    		int signatur;
    		string titel;
    		bool entliehen;
    
    	public:		
    		Medium();		
    		Medium(bool) { this->entliehen = false; }		
    		void show_Medium();
    		void entleihe_Medium();
    		void rueckgabe_Medium();
    		int get_signatur() { return signatur; }
    };
    
    class Buch: public Medium {
    	int seitenzahl;
    
    	public:
    		Buch();
    		void show_Medium();
    };
    
    class Video: public Medium {
    	double spieldauer;
    
    	public:
    		Video();
    		void show_Medium();
    };
    

    Dazu habe ich zwei Datein:
    Die erste main.cpp - ist zuständig für Ein-/Ausgabe, Funktionsuafrufe und Arrayverwaltung.
    Die zweite Datei binhaltet die Funktionen sowie die dazugehörigen Ein-/Ausgaben.

    So, wenn ich das Programm starte, werde ich aufgefordert etwas zu wählen z.B. ein neues Buch anlegen ...passiert alles in der erten Datei: Eingabe, Arrayzähler -> neues Buch:

    arr_buecher[buecher_anzahl] = new Buch;
    

    So, nun gelangt man zur zweiten Datei:

    Buch::Buch(): Medium(false) {  
    	entliehen = false;	
    		do {
    		cin.clear();	
    		cin.ignore( 100, '\n' );
    		cout << "Bitte Buchdaten eingeben: Signatur, Seitenzahl und Titel\n\n";
    		cout << "Signatur: ";
    	} while (!(cin >> signatur) && cin.fail());
    	cout << "Seitenzahl: ";
    	cin >> seitenzahl;
    	cout << "Titel: ";
    	cin.ignore( 100, '\n' );
    	getline(cin, titel);		
    	cout << "\nDie Buchdaten wurden gespeichert.\n\n";
    }
    

    Jetzt kommt die Header-Datei ins Spiel mit dem besagten:

    Medium(bool) { this->entliehen = false; }
    

    Ist das alles passiert und ich schau mir die Liste der Objekte an, habe ich nur ein Buch angelegt.
    Lasse ich

    Medium(bool) { this->entliehen = false; }
    

    weg, habe ich ein Medium und ein Buch angelegt.

    Und jetzt meine Frage:
    Was macht diese Initialisierung und der this-Zeiger?


  • Mod

    Nein, du hast garantiert ein Medium angelegt. Woher kommt diese Liste? Die ist falsch!

    Was macht diese Initialisierung und der this-Zeiger?

    Was meinst du, was die machen sollen? Das ist einer der Konstruktoren von Medium. Den this-Zeiger kann man sich sparen, aber manche Leute schreiben ihn hin. Er besagt eben, dass das entliehen sich auf eben diesen Member des Mediums bezieht. Die ganze Aktion kann (und sollte) man natürlich auch gleich in die Initialisierungsliste von Medium packen.

    P.S.: Mir kommt da gerade ein böse Verdacht: Du hast den Code nicht selber geschrieben? Oder größtenteils anderen Code nachgeahmt, ohne ihn zu verstehen? Weißt du überhaupt, wie Konstruktoren, Vererbung & Co. grob funktionieren?



  • Nein, du hast garantiert ein Medium angelegt. Woher kommt diese Liste? Die ist falsch!

    Die Liste wird nach Auswahl angezeigt.
    Wieso ist die Liste falsch? Sobald ich ein Objekt anlege wird der Array-Zähler für das angelegte Objekt erhöht. Das passiert aber außerhalb der Funktion.

    if (buecher_anzahl < MAXM) {	
    					arr_buecher[buecher_anzahl] = new Buch;
    					buecher_anzahl=buecher_anzahl+1;
    

    Wenn ich dann die Liste sehen will, werden nur die Objekte angezeigt, die adressiert wurden:

    if (arr_medien[0] != NULL || arr_buecher[0] != NULL || arr_videos[0] != NULL) {
    					cout << endl;
    					for (int i = 0; i < medien_anzahl; i=i+1) 
    					arr_medien[i]->show_Medium();
    
    					for (int i = 0; i < buecher_anzahl; i=i+1) 
    					arr_buecher[i]->show_Medium();
    
    					for (int i = 0; i < video_anzahl; i=i+1)
    					arr_videos[i]->show_Medium();
    					cout << endl;
    				} 
    				else {
    					cout << "\nKeine Medien vorhanden\n\n";
    

    Natürlich verstehe ich alles was hier drin steht. Diese Funktion mit dem this-Zeiger sollte ich vom Lehrer eintragen, eben das verstehe ich nicht.



  • Warum hast Du drei Arrays?
    Es reicht doch

    Medium* arr_medien[MAXM]
    

    Ist ein Medium nicht etwas abstraktes? Da stimmt irgendwas nicht mit der Übung...

    djhaefd schrieb:

    Diese Funktion mit dem this-Zeiger sollte ich vom Lehrer eintragen, eben das verstehe ich nicht.

    "Diese Funktion" ist auch nur ein weiterer Konstruktor von Medium. Wenn der nicht da ist, funktionieren die (Standard-)Konstruktoren von Buch u. Video, die Du zeigst doch gar nicht.


  • Mod

    djhaefd schrieb:

    Die Liste wird nach Auswahl angezeigt.
    Wieso ist die Liste falsch? Sobald ich ein Objekt anlege wird der Array-Zähler für das angelegte Objekt erhöht. Das passiert aber außerhalb der Funktion.

    Und somit bekommst du gar nicht mit, dass da ein Medium entsteht, wenn ein Buch entsteht. Diese Art des Zählens zählt nämlich nicht die wirklich konstruierten Objekte, sondern es zählt, wenn du denkst, dass ein Medium entsteht. Deine Annahmen darüber sind jedoch falsch.

    Üblich wäre, dass die Objekte einen (statischen oder globalen) Zähler im Konstruktor (und zwar allen! Kopierkonstruktoren nicht vergessen!) erhöhen und im Destruktor wieder heruntersetzen. So kannst du Objekte verlässlich zählen.



  • Ok, ich verstehe alles was ihr vorschlägt, aber das bringt mich nicht weiter.
    Ja, ich könnte auch nur ein Array schreiben, und ja ich könnte Medium auch Pferd nennen, und dass ich beim Anlegen der Liste mogel, weiss ich auch. Meine einzige Frage war, was passiert wenn ich den Aufruf von einem Video/Buch durch** Buch::Buch(): Medium(false) ersetze und was dann die Funktion Medium(bool) { this->entliehen = false; } **macht...alles ganz unabhängig vom Programm.



  • Wenn Du eine Klasse Medium hast, von der die Klassen Buch und Video abgeleitet sind, dann ist jedes erstellte Buch auch ein Medium, ebenso wie jedes erstellte Video auch ein Medium ist.

    Du kannst keinen VW Golf bauen, ohne ein Auto zu bauen, weil ein VW Golf eben ein Auto ist.
    Aber Du hast natürlich trotzdem nur ein Objekt, d.h. Du hast zwar ein Buch und ein Medium, so wie Du einen Golf und ein Auto hast, aber deshalb hast Du nicht zwei Objekte.



  • djhaefd schrieb:

    Meine einzige Frage war, was passiert wenn ich den Aufruf von einem Video/Buch durch** Buch::Buch(): Medium(false) ersetze und was dann die Funktion Medium(bool) { this->entliehen = false; } **macht...alles ganz unabhängig vom Programm.

    Evtl. würde ich mir selbst an die Nase fassen und mich mal fragen, warum mich niemand versteht, wenn ich hier eine Frage stelle.
    Du postet lauter Code der nix mit dem Problem zu tun hat, anstatt ein Minimalbeispiel zu bringen...

    Ich versuch's nochmal.
    Dein Buch - mit dem Konstruktor und dem geerbten Mediumobjekt, dessen Konstruktor und dem member entliehen :

    +------------------+
    |       Buch       |
    +------------------+
    | Buch()           |
    | +--------------+ |
    | |    Medium    | |
    | +--------------+ |
    | | Medium(bool) | |
    | | entliehen    | |
    | +--------------+ |
    +------------------+
    

    Dein C'tor

    Buch::Buch() : Medium(false){}
    

    ruft den Konstruktor

    Medium::Medium(bool)
    

    des geerbten Mediumobjekts mit dem Argument false auf.
    Dieser Konstruktor

    Medium::Medium(bool) { this->entliehen=false; }
    

    ignoriert das Argument und setzt das Member entliehen auf false .
    this ist ein Zeiger auf das Objekt in dessen Methode wir uns gerade befinde. Also ein Medium* in diesem Fall.

    Hilft das?



  • Super, vielen Dank 👍


Anmelden zum Antworten