OOP - Konstruktoren
-
Hi Community,
ich sitze momentan bei einer Aufgaben fest und weiß nicht wie ich diese lösen soll. Es handelt sich um eine Schulaufgabe die wir vor ein paar Tagen bekommen haben und auch in der Schule besprochen haben. Leider liegen diese Daten in der Schule und über das Wochenende habe ich keine Möglichkeit an die Daten zu kommen. Zudem schreiben wir am Montag eine Klausur über 'Konstruktoren-Destruktoren' und da ich über das Wochenende hinweg für diese Klausur lernen möchte, benötige ich jetzt dringend Hilfe.
Folgende Aufgabenstellung:
- Erstellen eines Programmes namens 'angestellte1.cpp'
- Eine Klasse namens 'angestellt' erstellen
- Deklarierende Variablen 'nachname' und 'vorname' vom Typ string / 'brutto' vom Typ double
- Methoden (Funktion)
eingabe liest Vorname, Nachname und Bruttogehalt ein
ausgabe gibt Vorname, Nachname und Bruttogehalt aus
- Erstellen unterschiedlicher Konstruktoren entsprechend der folgenden ObjekteingabenObjekt
- Angestellter1 soll den Standardkonstruktor verwenden
- Angestellter2 einen Konstruktor mit drei Parametern
- Angestellter3 einen Konstruktor mit dem einen Parameter 'Bruttogehalt'So, mein bisheriger Code
// angestellte1.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung. // #include "stdafx.h" #include "iostream" #include "conio.h" using namespace std; class angestellt { private: int nac; string nachname, vorname; double brutto; public: angestellt(); ~angestellt(); angestellt(int nac); void eingabe(string nachname1, string vorname1, double brutto1); void ausgabe(); }; angestellt::angestellt(){;} angestellt::~angestellt(){;} angestellt::angestellt(int nac) { nr=nac; } int _tmain(int argc, _TCHAR* argv[]) { angestellt angestellter1(1); angestellter1.eingabe(); angestellter1.ausgabe(); angestellt angestellter2(2); angestellter2.eingabe(); angestellter2.ausgabe(); angestellt angestellter3(3); angestellter3.eingabe(); angestellter3.ausgabe(); getch(); return 0; } void angestellt::eingabe(string nachname1, string vorname1, double brutto1) { nachname=nachname1; vorname=vorname1; brutto=brutto1; } void angestellt::ausgabe() { cout<<"\n\nAngestellter"<<nr<<"\nNachname: "<<nachname<<"\nVorname: "<<vorname; cout<<"\nBruttogehalt: "<<brutto; }
Im Großen und Ganzen muss ich sagen, dass ich die Aufgabenstellung seit Anfang an nicht ganz verstanden habe und nun jetzt auf dem Schlauch stehe.
Das fertige Programm sollte ja dann folgendermaßen aussehen:
Angestellter1
Nachname: bla...
Vorname: bla...
Bruttogehalt: $$€€
usw...Was ich jetzt nicht verstehe ist, das Verwenden des Standardkonstruktors für Angestellter1, den Konstruktor mit drei Parametern für Angstellter2 und den Konstruktor für Angestellter3 mit dem Parametern 'Bruttogehalt'.
Für konstruktive Vorschläge wäre ich sehr dankbar!
MfG
sign.other
-
sign.other schrieb:
Was ich jetzt nicht verstehe ist, das Verwenden des Standardkonstruktors für Angestellter1, den Konstruktor mit drei Parametern für Angstellter2 und den Konstruktor für Angestellter3 mit dem Parametern 'Bruttogehalt'.
angestellt angestellter1(); // Standard-Konstruktor: leer angestellt angestellter2( "Heinz", "Müller", 10000 ); // 3 Parameter angestellt angestellter3( 7500 ); //Brutto-Gehalt
jetzt musst du nur noch passende Konstruktoren dafür schreiben
Und du weißt schon, dass man so eine Funktion:
void eingabe(string nachname1, string vorname1, double brutto1);
nicht einfach mit
eingabe();
aufrufen kann? Du musst doch Parameter übergeben? Ich würde vorschlagen, du verbringst dein Wochenende mit einem kleinen C++-TutorialNichtsdestotrotz kannst du natürlich weiterhin konkrete Fragen stellen!
-
Hmm mal nen bissel Basis:
#include <iostream> #include <string> /* 03 */ class angestellt { private: std::string nachname; std::string vorname; double brutto; public: angestellt() : brutto(0.0) /* 01 */ {} angestellt(std::string const& /* 02 */ nachname, std::string const& vorname, double brutto) : nachname(nachname), vorname(vorname), brutto(brutto) {} angestellt(double brutto) : brutto(brutto) {} public: void eingabe(); void ausgabe() const; /* 02 */ };
... soo soll die Klasse aussehen ^^
Also ...
01: Guck dir mal eine s.g. "Initialisierungsliste" an.
02: Guck dir mal Referenzen an.
+ Evtl. kannst du dir auch mal const-correctness angucken(aber nur wenn du den Rest hin bekommst :P)
03: Guck dir mal den Unterschied zwischen #include "..." und #include <...> an.Die Funktion eingabe soll mit std::cin (Eingabe-Stream) die Variablen nachname, vorname und brutto einlesen! Wenn bei den Namen auch Leerzeichen erlaubt sein sollen, musst du std::skipws als Stream-Modifikator nutzen oder einfach die Funktion std::getline(std::cin, ...).
Von deiner Variable "nac" steht nichts in der Aufgabenstellung. Die sollte dann auch raus gelassen werden. Wenn du sie dennoch drin haben möchtest, markiere sie als "unsigned", d.h. sie hat kein Vorzeichen(es sei denn du kennst einen Angestellten -21 odg. :P).
-
Danke euch beiden erst einmal!
Badestrand schrieb:
angestellt angestellter1(); // Standard-Konstruktor: leer angestellt angestellter2( "Heinz", "Müller", 10000 ); // 3 Parameter angestellt angestellter3( 7500 ); //Brutto-Gehalt
jetzt musst du nur noch passende Konstruktoren dafür schreiben
Muss ich dann für jedes Objekt ein Konstruktor schreiben oder muss ich bei der Funktion eingabe(); etwas ändern?
Weil jetzt tritt das Problem auf, dass die Funktion nur 3 Argumente akzeptiert.Badestrand schrieb:
Und du weißt schon, dass man so eine Funktion:
void eingabe(string nachname1, string vorname1, double brutto1);
nicht einfach mit
eingabe();
aufrufen kann?Hmm... jetzt bin ich irritiert. In der Schule haben wir das auch nicht anders gemacht.
Badestrand schrieb:
Du musst doch Parameter übergeben?
Ja, den Vornamen, Nachnamen und das Bruttogehalt.
Badestrand schrieb:
Nichtsdestotrotz kannst du natürlich weiterhin konkrete Fragen stellen!
Das tue ich hiermit!
-
sign.other schrieb:
Badestrand schrieb:
angestellt angestellter1(); // Standard-Konstruktor: leer angestellt angestellter2( "Heinz", "Müller", 10000 ); // 3 Parameter angestellt angestellter3( 7500 ); //Brutto-Gehalt
jetzt musst du nur noch passende Konstruktoren dafür schreiben
Muss ich dann für jedes Objekt ein Konstruktor schreiben oder muss ich bei der Funktion eingabe(); etwas ändern?
Das hat mit der Funktion eingabe noch nix zu tun! In den drei Zeilen werden nur drei Variablen erstellt, jede vom Typ der Klasse "angestellt". Wenn eine Variable deklariert wird (wie hier, "Klassenname Variablenname"), kann man an dieser Stelle auch den Konstruktor aufrufen. Um mehr Möglichkeiten zu haben, kann man auch mehrere Konstruktoren für eine Klasse schreiben; einer nimmt bsw keinen Parameter entgegen, einer nimmt 3 Parameter usw.
Einen Konstruktor für eine Klasse schreibst du z.B. so:class MeineKlasse { public: MeineKlasse() { cout << "Standard-Konstruktor" << endl; } MeineKlasse( int eine_zahl ) { cout << "Konstruktor mit einem Parameter: " << eine_zahl << endl; } MeineKlasse( string satz, int bla ) { cout << "Konstruktor mit 2 Parametern: " << satz << " " << bla << endl; } }; // Irgendwo: MeineKlasse a; // Hier wird der Standard-Konstruktor aufgerufen MeineKlasse b(); // Hier auch MeineKlasse c( 100 ); // Hier der Konstruktor mit dem einen int-Parameter MeineKlasse d( "haaaaaaaaallo", 98172387 ); // Und hier..? :)
Und guck mal hier: http://www.volkard.de/vcppkold/inhalt.html
-
Muss ich dann für jedes Objekt ein Konstruktor schreiben oder muss ich bei der Funktion eingabe(); etwas ändern?
Weil jetzt tritt das Problem auf, dass die Funktion nur 3 Argumente akzeptiert.Also laut der Aufgabenstellung soll deine Klasse "angestellt" 3 Konstruktorüberladungen haben.
01 Default (also ohne Parameter)
02 Name + Nachname + Gehalt
03 Gehalt
Das machst du wie oben geschrieben mit:public: angestellt() /* 01 */: brutto(0.0) {} angestellt(std::string const& nachname, std::string const& vorname, double brutto) /* 02 */ : nachname(nachname), vorname(vorname), brutto(brutto) {} angestellt(double brutto) /* 03 */ : brutto(brutto) {}
...
Dadurch hast du die Möglichkeit, wie Badestrand schon schrieb,angestellt angestellter1(); // Standard-Konstruktor: leer angestellt angestellter2( "Heinz", "Müller", 10000 ); // 3 Parameter angestellt angestellter3( 7500 ); //Brutto-Gehalt
zu machen.
Die Konstruktoren kannst du auch noch verkürzen, in dem du der 3. Konstruktorüberladung einfach einen Default-Value zuweißt.public: angestellt(std::string const& nachname, std::string const& vorname, double brutto) /* 02 */ : nachname(nachname), vorname(vorname), brutto(brutto) {} angestellt(double brutto = 0.0) /* 01 UND 03 */ : brutto(brutto) {}
Dann ist 01 und 03 die selbe Konstruktorüberladung. Das ist aber nicht explizit in der Aufgabenstellung verlangt, deswegen kannst du es auch lassen
Hmm... jetzt bin ich irritiert. In der Schule haben wir das auch nicht anders gemacht.
Das ist merkwürdig ... Das Problem dabei ist, dass in der Aufgabenstellung steht:
eingabe liest Vorname, Nachname und Bruttogehalt ein
. Wenn da jetzt stehen würde "[...] bekommt Vorname, Nachname und Bruttogehalt als Parameter übergeben [...]", wäre das, was du machen wolltest, korrekt. So musst du aber eine Funktion mit dem Funktionsrumpf void angestellt::eingabe() {} nutzen. In der Funktion nimmst du dann std::cin und std::getline(std::cin, dest) und std::string um dann Eingaben vom Benutzer zu verlangen.
std::cout << "Name: " << std::flush; std::string name; std::cin >> name; // std::getline(std::cin, name); falls auch Leerzeichen im Namen erlaubt sind.
usw.
-
Danke nochmals für eure Hilfe!
So, ich habe jetzt versucht eure Vorschläge, soweit ich diese richtig verstanden habe, mit in das Programm zu integrieren.
Wenn ich das Programm debuggen möchte, dann erhalte ich 3 Fehlermeldungen:Fehler 1.
angestellter1.eingabe();
error C2660: 'angestellt::eingabe': Funktion akzeptiert keine 0 Argumente
Fehler 2.
angestellter3.eingabe(7500);
error C2660: 'angestellt::eingabe': Funktion akzeptiert keine 1 Argumente
Fehler 3.
cout<<"Vorname: "<<vorname<<"\nNachname: "<<nachname<<"\nBruttogehalt: "<<brutto;
error C2679: Binärer Operator '<<': Es konnte kein Operator gefunden werden, der einen rechtsseitigen Operanden vom Typ 'std::string' akzeptiert (oder keine geeignete Konvertierung möglich)
Hier mein geänderter Code
// angestellte1.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung. // #include "stdafx.h" #include <iostream> #include <conio.h> using namespace std; class angestellt { private: std::string nachname, vorname; double brutto; public: angestellt(); ~angestellt(); angestellt(std::string vorname1, std::string nachname1, double brutto1); angestellt(double brutto1); void eingabe(std::string vorname1, std::string nachname1, double brutto1); void ausgabe(); }; int _tmain(int argc, _TCHAR* argv[]) { angestellt angestellter1(1); angestellter1.eingabe(); angestellter1.ausgabe(); angestellt angestellter2(2); angestellter2.eingabe("Heinz","Müller",10000); angestellter2.ausgabe(); angestellt angestellter3(3); angestellter3.eingabe(7500); angestellter3.ausgabe(); getch(); return 0; } angestellt::angestellt(){;} angestellt::~angestellt(){;} angestellt::angestellt(std::string vorname1, std::string nachname1, double brutto1) { vorname=vorname1; nachname=nachname1; brutto=brutto1; } void angestellt::eingabe(std::string vorname1, std::string nachname1, double brutto1) { vorname=vorname1; nachname=nachname1; brutto=brutto1; } void angestellt::ausgabe() { cout<<"Vorname: "<<vorname<<"\nNachname: "<<nachname<<"\nBruttogehalt: "<<brutto; }
Irgendwie versteht das Programm noch nicht, dass bei 'angestellter1.eingabe();' keine Eingabe erfolgt bzw. der Standardkonstruktor verwendet werden soll und bei 'angestellter3.eingabe(7500);' nur ein Wert eingegeben wird bzw. ein Konstruktor mit dem Parameter 'Bruttogehalt' verwenden soll.
Vielleicht sollte ich erwähnen, dass keine Bildschrimeingabe des Benutzers erforderlich sein soll, sondern die Werte direkt in das Progamm geschrieben werden.
-
Ich glaub eher, du hast es nicht ganz verstanden..;)
Pass auf, Konstruktoren sind eigentlich echt nicht schwer.. Man kann sie auch nicht einfach aufrufen wie man lustig ist.
Also, von vorne:
Du hast eine Klasse, "angestellt". Wenn man von einer Klasse eine Variable anlegt, wird beim Erstellen der Variable der Konstruktor aufgerufen, beim Zerstören der Variable der Destruktor. Zwischen dem erstellen und dem zerstören kannst du nur Funktionen der Klasse aufrufen.void IrgendeineFunktion() { angestellt herman; // Hier wird der Konstruktor aufgerufen herman.MacheDies(); herman.MacheDas(); herman.MacheJenes(); // So, hier ist der Block vorbei, die Variable wird zerstört und der Destruktor aufgerufen. }
Und wie gesagt, wenn eine Funktion ein paar Parameter erwartet, musst du sie ihr auch übergeben, das hat mit Konstruktoren nicht die Bohne zu tun:
int Multipliziere( int a, int b ) // Die Funktion erwartet zwei Zahlenwerte { return a * b; } void FunktionBla() { int m = Multipliziere( 10, 100 ); // Und wir geben ihr auch zwei Zahlenwerte // m enthält den Wert 1000 Multipliziere(); // Gibt nen Fehler, wie soll das auch gehen?? //Das hier geht auch: int laenge = 5; int breite = 9898; int ergebnis = Multipliziere( laenge, breite ); }
Du kannst dir Funktionen auch so vorstellen:
Angenommen, du hast nen Kumpel der gut rechnen kann (und du überhaupt nicht). So, du willst wissen, wie groß der Flächeninhalt von einem Kreis ist, du hast den Radius. Also sagst du deinem Kumpel: "Hey, rechne mal den Kreis-Flächeninhalt aus, der Radius ist 5 cm". Dein Kumpel rechnet kurz und sagt dir: "Der Flächeninhalt ist 85cm" (oder so).
In dem Fall ist dein Kumpel die Funktion "int RechneFlaecheninhaltVomKreisAus( int radius )", denn er bekommt von dir den Radius und gibt dir den Flächeninhalt zurück. Du "rufst ihn auf" mit dem Radius und bekommst den Flächeninhalt zurück.
Wie soll das gehen, wenn du ihm einfach nur sagst: "Hey, rechne mal den Flächeninhalt von nem Kreis aus!". ? Was soll er antworten? 100? 1000? Geht halt nicht, er braucht die Radius-Angabe.
-
Vielen Dank Badestrand für deine Bemühungen!
Ich sitze jetzt schon seit Freitagnachmittag und seit heute um 11:00 Uhr vor der Aufgabe und komme kein Stück voran.
Was ich an der Aufgabe nicht verstehe ist, dass mir dem Standardkonstruktor und mit den beiden Parameterübergaben. Keine Ahnung wie ich das erklären soll.
Bei anderen Aufgaben, mit anderer Aufgabenstellungen, hatte ich keine Probleme. Nur bei der jetztigen.
Kann mir niemand einen Lösungsansatz verraten? Es soll niemand für mich die komplette Aufgabe lösen, um Gottes Willen, nur einen kleinen Lösungsansatz damit ich auf den richtigen Zug aufspringe. Sonst muss ich die Aufgabe auslassen, weil ich nicht mehr weiter weiß.MfG
sign.other
-
Du musst dir nur mal überlegen ob die Methode "eingabe"
a) Keinen Parameter übergeben bekommen soll und von der Konsole die Werte einliest oder
b) alle drei Werte übergeben bekommen soll, damit sie ihre internen Variablen diese Werte zuweisen kann
-
// angestellte1.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung. // #include "stdafx.h" #include <iostream> #include <conio.h> using namespace std; class angestellt { private: string nachname, vorname; double brutto; public: angestellt(); // Standardkonstruktor ~angestellt(); // Destruktor angestellt(string nac, string vor, double bru); // Konstruktor mit 3 Parameter angestellt(double bru); // Konstruktor mit Parameter 'Bruttogehalt' void eingabe(); // HIER WEISS ICH NICHT WEITER // void ausgabe(); }; int _tmain(int argc, _TCHAR* argv[]) { angestellt angestellter1(1); angestellter1.eingabe(); // Verwendet Standardkonstruktor angestellter1.ausgabe(); angestellt angestellter2(2); angestellter2.eingabe("Peter","Lustig",4500); // Verwendet Konstruktor mit 3 Parameter angestellter2.ausgabe(); angestellt angestellter3(3); angestellter3.eingabe(2800); // Verwendet Konstruktor mit Parameter 'Bruttogehalt' angestellter3.ausgabe(); getch(); return 0; } angestellt::angestellt(){;} // Standardkonstruktor angestellt::~angestellt(){;} // Destruktor angestellt::angestellt(string nac, string vor, double bru) // Konstruktor mit 3 Parameter { nachname=nac; vorname=vor; brutto=bru; } angestellt::angestellt(double bru) // Konstruktor mit Parameter 'Bruttogehalt' { brutto=bru; } void angestellt::eingabe() { // HIER WEISS ICH NICHT WEITER // } void angestellt::ausgabe() { }
Ist das Ansatzweise richtig?
MfG
sign.other
-
Die Parameter des Konstruktors gibst du implizit beim Erstellen einer Objektinstanz mit an, d.h. deine Initialisierungen
angestellt angestellter1(/* das sind deine Konstruktorparameter!*/ 1); //bzw. angestellt angestellter2(2);
würden, aufgrund der übergebenen Parameter, den Konstruktor mit der Angabe des Bruttogehaltes aufrufen, du legst also zwei Angestellte mit einem Gehalt von 1 bzw. 2€ an, schlimmer als Hartz4
Die Initialisierung mithilfe eines Konstruktors mit 3 Paramtern würde also so aussehen:
angestellt angestellter1("Peter","Lustig", 4500);
Deine Methode eingabe() hat mit den Konstruktoren nicht das geringste zu tun!
Grüße,
Martin