Objekt in C++
-
rumcajs007 schrieb:
#include <iostream> class CPerson { public: CPerson(char[], char[], unsigned int); ~CPerson(); void vorname_anzeigen(); void nachname_anzeigen(); void alter_anzeigen(); void info(); protected: char vorname[], nachname[]; // hier liegt dein fehler... unsigned int alter; }; CPerson::CPerson(char add[], char name[], unsigned int age) {strcpy(vorname,add); strcpy(nachname,name); alter=age;} CPerson::~CPerson() {} void CPerson::vorname_anzeigen() {cout << "vorname : " << vorname << "\n";} void CPerson::nachname_anzeigen() {cout << "nachname : " << nachname << "\n";} void CPerson::alter_anzeigen() {cout << "alter : " << alter << "\n";} void CPerson::info() {CPerson::vorname_anzeigen();CPerson::nachname_anzeigen();CPerson::alter_anzeigen();} void main(void) { CPerson jemand("Vorname","Nachname",28); jemand.info(); cout << "Weiter mit beliebigen Taste..."; cin.get(); }dein fehler ist folgender:
du erstellst 2 char arrays aber mit undefinierter grösse...
und dann willst du da was reinschreibeneigendlich sollte der compiler schon mekcern, wenn icht dann sollte wenigstens das bestriebssystem meckern weil du unerlaubt in irgendeinen speicher schreibst...
nimm entweder von anfang an std::string oder versuchs mal mit nem char-pointer
#include <iostream> class CPerson { public: CPerson(char[], char[], unsigned int); ~CPerson(); void vorname_anzeigen(); void nachname_anzeigen(); void alter_anzeigen(); void info(); protected: char *vorname; char *nachname; unsigned int alter; }; CPerson::CPerson(char add[], char name[], unsigned int age) {strcpy(vorname,add); strcpy(nachname,name); alter=age;} CPerson::~CPerson() {} void CPerson::vorname_anzeigen() {cout << "vorname : " << vorname << "\n";} void CPerson::nachname_anzeigen() {cout << "nachname : " << nachname << "\n";} void CPerson::alter_anzeigen() {cout << "alter : " << alter << "\n";} void CPerson::info() {CPerson::vorname_anzeigen();CPerson::nachname_anzeigen();CPerson::alter_anzeigen();} void main(void) { CPerson jemand("Vorname","Nachname",28); jemand.info(); cout << "Weiter mit beliebigen Taste..."; cin.get(); }sollte so eig klappen doer? (nicht getestet)
-
hallo.
vielen dank schon mal für eure schnellen antworten.
vieleicht sollte ich schon am anfang sagen dass ich nicht mit string objekten und pointern coden wollte obwohl es das sinvoller wäre das ist fakt. schreibe gerade so ein tutorial mal für mich was ich schon so gelernt habe und wollte klein anfangen. ich werde jetz mal versuchen die variablen zu präzisieren und werde dann nochmal berichten. :pgruss.
-
"Klein" fängt man aber bestimmt nicht mit char-Pointern an...
-
rumcajs007 schrieb:
...vieleicht sollte ich schon am anfang sagen dass ich nicht mit string objekten und pointern coden wollte obwohl es das sinvoller wäre das ist fakt. ...
Also "Du willst nicht" mag Fakt sein, aber es bleibt trotzdem Quatsch - besonders, wenn Du selbst schon erkannt hast dass "... das sinnvoller wäre ...".
Ich hoffe, Du machst nicht allzuviel in Deinem Leben wider besseres Wissen.und wenn Du Dir um die "Didaktik" (also einen sinnvollen Lern-/Lehrweg) machst, rate ich, Dir einfach mal das erste Post in diesem Thread anzusehen (also Dein eigenes) - da siehst ein Beispiel für die Probleme, die man bekommt, wenn man Anfängern Zeichenkettenverwaltung mit char* zumutet, statt gleich den richtigen Typ (std::string) zu verwenden.... es scheint also nicht wirklich der bessere Lerneinstieg zu sein.
Gruß,
Simon2.
-
CPerson::CPerson(char add[], char name[], unsigned int age)
rumcajs007 schrieb:
vieleicht sollte ich schon am anfang sagen dass ich nicht mit string objekten und pointern coden wollte ...
Dir ist aber hoffentlich klar dass "add" und "name" 2 POINTER SIND.
Wenn nicht solltest du vermutlich mal deine C++ Syntaxkenntnisse aufbessern.----
Andy2211 schrieb:
"char*"
Wenn dann bitte "char const*".
-
LordJaxom schrieb:
"Klein" fängt man aber bestimmt nicht mit char-Pointern an...
wollte ich auch nicht

hustbaer schrieb:
CPerson::CPerson(char add[], char name[], unsigned int age)
rumcajs007 schrieb:
vieleicht sollte ich schon am anfang sagen dass ich nicht mit string objekten und pointern coden wollte ...
Dir ist aber hoffentlich klar dass "add" und "name" 2 POINTER SIND.
Wenn nicht solltest du vermutlich mal deine C++ Syntaxkenntnisse aufbessern.----
Andy2211 schrieb:
"char*"
Wenn dann bitte "char const*".
das war ein verbessertes code nicht von mir

sooo, hab jetzt die zwei char variablen auf 25 gesetzt mit erfolg, die werte werden übergeben bzw. angezeigt/übernomen.
... void info(); protected: char vorname[25], nachname[25]; unsigned int alter; ...
-
rumcajs007 schrieb:
vieleicht sollte ich schon am anfang sagen dass ich nicht mit string objekten und pointern coden wollte obwohl es das sinvoller wäre das ist fakt. schreibe gerade so ein tutorial mal für mich was ich schon so gelernt habe und wollte klein anfangen...
Da jedes gute C++ Tutorial, ob nun für dich oder für andere nicht mit char-Arrays oder char* Pointern beginnt, sondern gleich mit std::string, ist es - gelinde gesagt - Schwachsinn.
C-Arrays sowie Pointer sind meines Erachtens erst später sinnvoll da sich z.B. Arrays nicht so verhalten wie von anderen C++ Objekten gewohnt, und Zeiger mit Sicherheit auch nicht das sind, was ein Anfänger gleich versteht.
Eine weitere Sache: Ausgaben sollte man möglichst von der restlichen Logik entkoppeln. Eine Personenklasse hat meines erachtens nichts mit der UI zu tun.
Weiterhin trennt man Implementation und Deklaration voneinander (cpp/h), und es ist sinnvoll auch in der Deklaration die Parameternamen anzugeben (alleine schon da man schneller mal einen Header überblickt, als die zugehörige Implementierung, und die Implementierung den Benutzer einer Klasse egal sein sollte solange man sich an deren Schnittstelle hält.
Und: Wenn du mit Arrays/Zeigern arbeitest musst du dich auch um den Kopierkonstruktor, Zuweisungsoperator und die Speicherfreigabe kümmern...
"void main" gibt es nicht!
Zu guter letzt hilft sinnvolles einrücken beim Lesen...
Mal eine andere Variante (ungetestet):
// Person.h
#ifndef PERSON_HEADER #define PERSON_HEADER #include <string> class Person { public: Person( std::string const & vorname, std::string const & nachname, unsigned int alter); ~Person(); std::string GetVorname() const; void SetVorname( std::string const & vorname); std::string GetNachname() const; void SetVorname( std::string const & nachname); unsigned int GetAlter() const; void SetAlter( unsigned int alter); private: std::string vorname; std::string nachname; unsigned int alter; }; #endif// Person.cpp
#include "Person.h" Person::Person( std::string const & vorname, std::string const & nachname, unsigned int alter) : vorname(vorname), nachname(nachname), alter(alter) {} Person::~Person() {} std::string Person::GetVorname() const { return vorname; } void Person::SetVorname( std::string const & vorname) { this->vorname = vorname; } std::string Person::GetNachname() const { return nachname; } void Person::SetNachname( std::string const & nachname) { this->nachname= nachname; } unsigned int Person::GetAlter() const { return alter; } void Person::SetAlter( unsigned int alter) { this->alter = alter }// PersonAusgabe.h
#ifndef PERSONAUSGABE_HEADER #define PERSONAUSGABE_HEADER class Person; void Print( Person const & person); #endif// PersonAusgabe.cpp
#include <iostream> #include "Person.h" void Print( Person const & person) { std::cout << "Vorname : " << person.GetName() << "\n" << "Nachname : " << person.GetNachname() << "\n" << "Alter : " << person.GetAlter() << "\n"; }// main.cpp
#include <iostream> #include "Person.h" #include "PersonAusgabe.h" int main() { Person jemand("Vorname", "Nachname", 28); Print(jemand); std::cout << "Weiter mit beliebigen Taste..."; std::cin.get(); }
-
ja, das sieht echt profi mässig aus, danke danke. jetzt weiss ich wie ich das ganze am beste unterbringen kan

apropo const, wenn die werte aucvh mal verändert werden sollen darf ich dann const nicht mehr anwenden stimmts ?
bitte alles erstmal ohne zeiger

noch ein fehler gefunden, man darf doch nicht zig mal iosream includen oder ?

-
Hi,
also zu der const geschichte. Const verwendet man ja hauptsächlich um zu zeigen, ob in einem code eine variable geändert wird oder was genau da passiert (viel übersichtlicher).Es gibt const variablen, die einen festen wert haben und dann gibt es aber auch const zeiger, das ist dann sowas wie eine referenz, sprich ein const zeiger muss immer auf etwas zeigen, der kann nie auf NULL.
Den "iostream" musst du da includen wo er notwendig ist. Wenn deine Klasse mit dem "iostream" arbeitet wird dieser in der header datei der Klasse 1x inkludiert.
Gruß Andy
-
rumcajs007 schrieb:
ja, das sieht echt profi mässig aus, danke danke. jetzt weiss ich wie ich das ganze am beste unterbringen kan

Ich will nicht sagen das es unbedingt das Optimum ist, aber es ist mit Sicherheit eine sauberer Alternative, zumal du dir Zeiger sparst (Und C-Arrays haben mit Zeigern nicht grade wenig zu tun).
rumcajs007 schrieb:
apropo const, wenn die werte aucvh mal verändert werden sollen darf ich dann const nicht mehr anwenden stimmts ?
Also eine Kurzzusammenfassung dessen, was ich im Code mit const abbilde, und vielleicht noch eine erklärung warum ich this verwende, und was es bedeutet.
// Diese Methode modifiziert keine Werte innerhalb der Klasse. Dies kann (und sollte man) // mit const hinter der Parameterliste signalisieren. Das hat den Vorteil, das diese Methode // Auch auf konstante Objekte angewendet werden kann (Thema: "const correctness") std::string Person::GetVorname() const { return vorname; } // Für diese Methode trennen wir mal mehrere Aspekte: // 1. std::string const & vorname // Alternative Schreibweise: const std::string & vorname // Ich weiß nicht in wie weit du dich mit Referenzen auskennst. Grundsätzlich gibt es mehrere // Formen wie man Variablen übergeben kann, ich zeige hier mal die 3 Varianten ohne Zeiger auf: // a) Call-by-Value // void Person::SetVorname(std::string vorname); // => Hier wird der übergebene Wert kopiert. Dies ist bei den Basisdatentypen wie // int, short, float... meist das Optimum, bei Objekten sollte man unnötige Kopien aber // vermeiden. Eine Änderung an der Kopie betrifft den Originalwert nicht. // b) Call-by-Reference // void Person::SetVorname(std::string & vorname); // => Referenzen sind sogenannte Aliasnamen. Das heißt, das du hier auf den Originalobjekt arbeitest, // das der Funktion übergeben wurde. Würdest du diesen Wert ändern, würde er auch an // der Stelle des Aufrufes geändert werden, da du wie gesagt auf ein und den selben Objekt // arbeitest. // Referenzen solltest du immer einsetzen wenn du einen Übergebenen Wert manipulieren willst, // und diesen nicht als Rückgabewert übergibst. // c) Call-by-Const-Reference // void Person::SetVorname(std::string & vorname); // => Wie bei b, du arbeitest also mit dem Original, nur das du dieses nicht verändern darfst. // Diese Übergabe solltest du bei allen Objektübergaben verwenden, wenn der Wert nicht // manipuliert werden soll (Dies ist meist der Regelfall). // 2. this->vorname = vorname // Dir ist vielleicht aufgefallen das bei mir die Membervariable genauso heißt wie der // Übergabeparameter. Ich mag es nicht gekünstelte Namen zu verwenden nur um dieses Problem zu // umgehen. Wie kann ich aber nun zwischen den beiden Unterscheiden? // Grundsätzlich haben lokale Variablen immer Vorrang (Ein Parameter ist hier wie eine lokale // Variable anzusehen. Wenn ich also nur "vorname" schreibe, beziehe ich mich hier auf den // Parameter. Der this-Zeiger verweist auf das aktuelle Objekt, und darüber kann ich immer // auf die Membervariable verweisen. Sprich: "this->vorname = vorname" bedeutet, das // ich die lokale Variable "vorname" der Membervariable "vorname" zuweise. void Person::SetVorname( std::string const & vorname) { this->vorname = vorname; }rumcajs007 schrieb:
bitte alles erstmal ohne zeiger

Wo sind bitte Zeiger in meinen Code? (Wenn man mal von this absieht, und der verweist einfach nur auf das aktuelle Element; und ich hoffe diesen nun gut beschrieben zu haben.
rumcajs007 schrieb:
noch ein fehler gefunden, man darf doch nicht zig mal iosream includen oder ?

Wieso nicht. Dazu gibt es die "Includeguards" (gleich dazu mehr) im Header. Dir fallen vielleicht in meinen Header die Makros auf? Dies sind die Includeguards. Ein Includeguard verhindert das Header mehrfach abgearbeitet werden. Es ist sogar guter Stil wenn man immer sieht was eine Datei verwendet, und nicht Includes in anderen Headern versteckt. Zudem sollte man immer (sofern möglich) Includes in den Source, nicht in den Header legen.
Thema Includeguard:
// Headerdatei #ifndef EINDEUTIGERNAME // Dieser Name ist eindeutig zu benennen! #define EINDEUTIGERNAME // <-- Hier der eigentliche inhalt #defineWenn du so Header schreibst (und wirklich eindeutige Bezeichner wählst), kannst du einen Header nahezu beliebig includieren. Das einzige was du so nicht auflösen kannst, sind gegenseitige Abhängigkeiten (Hier google im Zweifel nach "forward declaration" oder "Vorwärtsdeklaration").
cu André
P.S: Link zu "const correctness"