Zeiger auf Klasse
-
Hi @all,
ich weis, dass habt ihr schon öfters gehört. "Ich bin neu hier und habe bisher selten was mit C++ gemacht und brauche mal eure Hilfe."
Ich muss eine Aufgabe für die Schule lösen und weis nicht so recht weiter.
Aufgabe:
Implementieren Sie eine Klasse Medium, die die privaten Attribute Titel, Sprache und Preis besitzen soll. Die Schnittstelle der Klasse soll aus folgenden Methoden bestehen:
· Konstruktor, der die drei Attribute mit den übergebenen Werten initialisiert.
· Methode print, die die Werte der Attribute auf dem Bildschirm ausgibt.Implementieren Sie eine Klasse Buch, die von Medium erbt. Buch erweitert Medium um die privaten Attribute Autor und ISBN. Die Schnittstelle der Klasse soll aus folgenden Methoden bestehen:
· Konstruktor mit fünf Parametern, über den alle Attribute inklusive der ererbten initialisiert werden.
· Methode print, die die Werte der fünf Attribute auf dem Bildschirm ausgibt.Implementieren Sie eine Klasse Film, die von Medium erbt. Film erweitert Medium um die privaten Attribute Regisseur und Hauptdarsteller. Die Schnittstelle der Klasse soll aus folgenden Methoden bestehen:
· Konstruktor mit fünf Parametern, über den alle Attribute inklusive der ererbten initialisiert werden.
· Methode print, die die Werte der fünf Attribute auf dem Bildschirm ausgibt.Schreiben Sie eine geeignete main-Funktion zum Testen Ihrer Klasse. Benutzen Sie dazu ein Feld von Zeigern auf Medium. Füllen Sie das Feld mit Zeigern auf Objekte der drei Klassen. Durchlaufen Sie das Feld und rufen Sie für jedes Objekt die Funktion print auf. Die Implementierung Ihrer Klassen muß sicherstellen, daß dabei jeweils die Methode des referenzierten Objekts aufgerufen wird.
Soweit die Aufgabe. Da ich schön öfters was mit PHP gemacht habe, kenne ich mich mit Programmieraufgaben soweit gut aus. Mein Problem basiert jetzt auf den Zeigern mit C++.
Meine Klassen habe ich soweit. Die Klassen Buch und Film erben jeweils von Medium und sind vom Typ public. Jede der drei Klassen besitzt eine Methode print() die auch als public deklariert wurde. Meine main-Funktion sieht folgendermaßen aus:int main() { int size = 6; medium *data[size]; // Objekte initialisieren medium medium1("Medium1", "Deutsch", 19.50); medium medium2("Medium2", "Deutsch", 29.50); book book1("Buch1", "Deutsch", 19.50, "Autor1", "123-456-789"); book book2("Buch2", "Deutsch", 29.50, "Autor2", "987-654-321"); movie movie1("Film1", "Deutsch", 19.50, "Autor1", "123-456-789"); movie movie2("Film2", "Deutsch", 29.50, "Autor2", "987-654-321"); // Zeiger im Array speichern data[0] = &medium1; data[1] = &medium2; data[2] = (medium*) &book1; data[3] = (medium*) &book2; data[4] = (medium*) &movie1; data[5] = (medium*) &movie2; for(int counter=0; counter<size; counter++) { data[counter]->print(); } system("PAUSE"); return 0; }
Die Print-Methoden sind die folgenden:
void medium::print() { printf("Titel: %s\nSprache: %s\nPreis: %.2f\n\n", title, lang, price); } void book::print() { printf("Titel: %s\nSprache: %s\nPreis: %.2f\nAutor: %s\nISBN-Nummer: %s\n\n", title, lang, price, author, isbn); } void movie::print() { printf("Titel: %s\nSprache: %s\nPreis: %.2f\nAutor: %s\nISBN-Nummer: %s\n\n", title, lang, price, author, isbn); }
Die Ausgabe bringt mir folgendes:
Titel: Medium1 Sprache: Deutsch Preis: 19.50 Titel: Medium2 Sprache: Deutsch Preis: 29.50 Titel: Buch1 Sprache: Deutsch Preis: 19.50 Titel: Buch2 Sprache: Deutsch Preis: 29.50 Titel: Film1 Sprache: Deutsch Preis: 19.50 Titel: Film2 Sprache: Deutsch Preis: 29.50
In der Schleife durchlaufe ich mein Array, indem ich die einzelnen Adressen der Objekte gespeichert habe. Warum ruft er mir die immer die print-Methode der Klasse Medium auf und nicht die der jeweiligen vererbten Klassen?
Vielleicht kann mir einer einen Denkanstoß geben.Vielen Dank schon im voraus,
Steffenchen
-
Dafür brauchst du virtuelle Methoden.
Es sollte reichen die Methode "print" als virtual zu deklarieren.class medium { ... virtual void print(); };
Wie das genau funktioniert kannst du zum Beispiel da nachlesen.
-
Danke für deine Hilfe, godlikebot.
Habe das analog des Beispiels mal probiert.
int size = 3; medium* array[size]; for (int count=0; count<size; count++) { if ((count%3) == 0) { array[count] = new medium("Medium1", "Deutsch", 19.50); } else if ((count&3) == 1) { array[count] = new book("Buch1", "Deutsch", 19.50, "Autor1", "123-456-789"); } else { array[count] = new movie("Film1", "Deutsch", 19.50, "Autor1", "123-456-789"); } } for (int count=0; count<size; count++) { array[count]->print(); }
Allerdings erhalte ich jetzt beim Ausführen folgendes:
Titel: Medium1 Sprache: Deutsch Preis: 19.50 Titel: Buch1 Sprache: Deutsch Preis: 0.00 Titel: Film1 Sprache: Deutsch Preis: 0.00
Es fehlen also beim Objekt Buch und Film noch ein paar Daten. Woran könnte das jetzt liegen?
-
wie sieht es mit deinen konstruktoren aus?
sind die richtig?
oder ist was bei den print() methoden nicht richtig?
rufst du die print() methode aus der basisklasse auch noch auf?
-
wie sieht es mit deinen konstruktoren aus?
sind die richtig?Anbei mal meine Klassen:
/** * Klasse zur Verwaltung von Medien */ class medium { private: char *title, *lang; float price; public: medium(char *my_title, char *my_lang, float my_price); virtual void print(); }; /** * Konstruktor * * @param char my_title Titel des Buches * @param char my_lang Sprache des Buches * @param float my_price Preis des Buches */ medium::medium(char *my_title, char *my_lang, float my_price) { title = my_title; lang = my_lang; price = my_price; } /** * gibt die Werte auf dem Bildschirm aus */ void medium::print() { printf("Titel: %s\nSprache: %s\nPreis: %.2f\n\n", title, lang, price); } /** * Klasse zur Verwaltung von Büchern */ class book : public medium { private: char *title, *lang, *author, *isbn; float price; public: book(char *my_title, char *my_lang, float my_price, char *my_author, char *my_isbn); void print(); }; /** * Konstruktor * * @param char my_title Titel des Buches * @param char my_lang Sprache des Buches * @param float my_price Preis des Buches * @param char my_author Autor des Buches * @param char my_isbn ISBN-Nummer des Buches */ book::book(char *my_title, char *my_lang, float my_price, char *my_author, char *my_isbn) : medium(my_title, my_lang, my_price) { title = my_title; lang = my_lang; price = my_price; author = my_author; isbn = my_isbn; } /** * gibt die Werte auf dem Bildschirm aus */ void book::print() { printf("Titel: %s\nSprache: %s\nPreis: %.2f\nAutor: %s\nISBN-Nummer: %s\n\n", title, lang, price, author, isbn); }
oder ist was bei den print() methoden nicht richtig?
Eigentlich müsste bei den beiden Print-Ausgaben des Buches/Filmes der Preis richtig erscheinen und weiterhin der Author und die ISBN-Nummer angezeigt werden. Ich denke, dass er irgendwo die Print-Methode falsch auswählt.
rufst du die print() methode aus der basisklasse auch noch auf?
das müsste er ja in der letzten Schleife automatisch machen. Er geht ja die Objekte im Array durch und ruft die jeweiligen print-Methoden auf, so würde ich es denken.
-
frage am rande:
/** * Konstruktor * * @param char my_title Titel des Buches * @param char my_lang Sprache des Buches * @param float my_price Preis des Buches * @param char my_author Autor des Buches * @param char my_isbn ISBN-Nummer des Buches */
müsst ihr das machen?
ich empfinde diese information als ziemlich redundant
-
jo finde ich auch, dass das redundant ist....
wenn ich das programm bei mir kompiliere, dann gibt er die richtigen sachen aus... also ich kann keinen fehler so mehr finden....
-
eine sache gibts noch zu bemängeln:
class book : public medium { private: char *title, *lang, *author, *isbn; float price; public: book(char *my_title, char *my_lang, float my_price, char *my_author, char *my_isbn); void print(); };
price title und lang sind bereits in medium enthalten, diese information ist also redundant da schon vorhanden.
Nun fragst du dich sicherlich: wie kann ich denn auf die variablen von medium zugreifen?
ganz einfach: du machst sie einfach protected anstatt private
-
ich glaube habe auch noch eine:
book::book(char *my_title, char *my_lang, float my_price, char *my_author, char *my_isbn) : medium(my_title, my_lang, my_price) { title = my_title; //ist das nicht überflüssig??? lang = my_lang; price = my_price; author = my_author; isbn = my_isbn; }
titel, lang und price können doch auch wegfallen... er benutzt doch schon den elementinitialisierer(? weiß nicht genau, ob der so heißt ?)
@otze:
er muss sie doch gar nicht protected machen, wenn er mit dem konstruktor der medium klasse die elemente initialsisiert.... der konstruktor ist doch public, also kann er auch auf die private elemente zugreifen..
oder irre ich mich da? ich programmiere noch nicht so lange...
-
direkt zugriff auf private geht bei public vererbung NIE, nur bei private vererbung und friend ist das möglich
//edit natürlich initialisiert er die werte im ctor der klasse, aber wenn man etwas weiter denkt, kann das nichts werden, denn wenn er irgendwo in der Buch Klasse den preis ändern wollte, dann würde sich das nicht auf die basisklasse auswirken.
-
ja, aber kann man dafür nicht in der basisklasse setter-methoden machen, die dann die abgeleitete klasse aufrufen kann, um den preis zu ändern? es wäre doch möglich, oder nicht?
ist das dann schlechter stil, wenn man getter/setter-methoden verwendet?
wie gesagt, ich kenne die grundlagen, weiß aber nicht, wann was besser ist, oder was man generell vermeiden sollte... kannste mir da ein paar tipps geben? würde mich sehr darüber freuen.
-
in dem fall währe es schlechter stil, da die abgeleitete Klasse keine separaten werte besitzen soll, sie soll nur erweiterungen bieten(und selbst das muss sie nicht).
und nur so am rande: wieso 2x die gleichenw erte an unterschiedlichen stellen speichern, wenn ans a) einfacher b) schöner und c) platzsparender machen kann
-
ich habe ja seinen sourcecode geändert.... bei mir enthält die abgeleitete klasse nur noch die zusätzlichen elemente... (also ohne price usw.)
und ich benutze die Liste der STL.. zudem habe ich char* zu string geändert...
-
wozu std::list?
-
otze schrieb:
wozu std::list?
verstehe ich jetzt nicht?
ich habe die Liste der STL benutzt, damit ich ein bisschen mehr lerne, da ich die sachen der STL nicht so oft benutze... übung macht den meister
-
ahso
dachte, es hätte speziell was mit diesem problem zu tun
-
otze schrieb:
frage am rande:
/** * Konstruktor * * @param char my_title Titel des Buches * @param char my_lang Sprache des Buches * @param float my_price Preis des Buches * @param char my_author Autor des Buches * @param char my_isbn ISBN-Nummer des Buches */
müsst ihr das machen?
ich empfinde diese information als ziemlich redundantJa leider. Ich würde auch gerne darauf verzichten, aber es wird ja gefordert. Aber in Zukunft werde ich hier diese Informationen herauslassen.
-
leech schrieb:
ich habe ja seinen sourcecode geändert.... bei mir enthält die abgeleitete klasse nur noch die zusätzlichen elemente... (also ohne price usw.)
und ich benutze die Liste der STL.. zudem habe ich char* zu string geändert...Sorry, dass ich erst jetzt antworte. Hatte gestern Abend nach langem Probieren nicht mehr die Nerven und bin einfach ins Bett. Das würde bedeuten, dass ich in den abgeleiteten Klassen jeweils nur noch Autor und ISBN-Nummer benötige, da ich die anderen drei Sachen bereits in Medium vorhanden habe.
Soweit ich weis, kann ich den Typ string nur benutzen, wenn ich diese Bibliothek explizit einbinde, richtig? Und das darf ich leider nicht
-
leech schrieb:
wenn ich das programm bei mir kompiliere, dann gibt er die richtigen sachen aus... also ich kann keinen fehler so mehr finden....
Kompilieren kann ich das ganze auch. Er rief allerdings bei den beiden Objekten vom Typ Buch und Film die print-Methode der Medium-Klasse auf. Vielleicht liegt es aber auch daran, dass ich die Attribute in den abgeleiteten Klassen noch einmal mit übernommen habe. Ich werde dies heute Abend mal ausprobieren.
So kam folgendes heraus:
Titel: Mein Titel Sprache: Deutsch Preis: 0.00
aber eigentlich müsste folgendes angezeigt werden
Titel: Buch1 Sprache: Deutsch Preis: 19.50 Autor: Autor1 ISBN: 123-456-789
Vielen Dank für eure Hilfe
Steffenchen
-
Nur so nebenbei.. Bist zufällig in Köln an der GSO?
Da würd die Aufgabenstellung nämlcih genau passen
-
Vernochan schrieb:
Nur so nebenbei.. Bist zufällig in Köln an der GSO?
Da würd die Aufgabenstellung nämlcih genau passenNein, in Frankfurt. Aber irgendwie cool zu hören, dass die Lehrer zum Teil das Rad auch nicht neu erfinden.