Aufgabe Klasse (Konstruktor / Destruktor)



  • // in .h:
    
    adresse(const char *stadt, const char *strasse, const char *tel);
    adresse();
    ~adresse(){ anzahl--; }
    
    static int anzahl;
    
    // in .cc/.cpp
    
    int adresse::anzahl = 0;
    
    adresse::adresse(const char *stadt, const char *strasse, const char *tel){
        this->stadt = string(stadt);
        this->strasse = string(strasse);
        this->tel = string(tel);
        anzahl++;
    }
    adresse::adresse(){
        stadt = string("ooooooooooo");
        strasse = string("xxxxxxxxxx");
        tel = string("mmmmmmmmm");
    }
    

    Müsste so in etwa da sein, was du willst. Zumindest das was ich glaube was du willst, was dank fehlendem Problem ja nicht ganz klar ist. 😉



  • Ich ergänze mal etwas:

    1. Wenn char-Vektoren (der Dozent meint hierbei nach den Übergaben zu urteilen char-Arrays) verlangt sind, darfst du nicht mit der Stringklasse arbeiten (auch wenn diese tatsächlich C++ ist) und musst auf die C-Funktionen (z.b. aus #include <cstring>) zurückgreifen.

    Sprich dein Dozent lehrt kein wirkliches C++, sondern irgendeine Mischung aus C und C++.

    2. Wenn dir Methoden vorgegeben werden solltest du diese auch verwenden, auch wenn mir unverständlich ist was diese Methode "void putAdr();" tun soll. Vom Namen in Kombination mit Rückgabewerten und Übergabeparameter macht sie keinen Sinn.

    3. Konstruktoren und Destruktoren sind syntaktisch wie Funktionen, nur das sie keinen Rückgabewert haben, also solltest du mit dieser Information in der Lage sein zumindest die Rümpfe entsprechend in deinen Code einzupflegen.

    4. Bitte niemals using namespace im Header einsetzen (Hat mehr Nach- als Vorteile!).

    5. In der Regel sollte die GUI (Hier Console) von der Logik getrennt sein. Besser statt "void setIrgendwas();" mit cin innerhalb durch "void setIrgendwas(typ value)" bei integralen Datentypen oder "void setIrgendwas(const typ& value)" bei Objekten verwenden.

    Fellhuhn hat schon einen Ansatz gepostet, der aber intern wieder die Stringklasse verwendet. Dies wäre zwar C++ aber laut Aufgabenstellung wie gesagt verkehrt.

    Anmerkung@Fellhuhn

    Fellhuhn schrieb:

    adresse::adresse(const char *stadt, const char *strasse, const char *tel){
        this->stadt = string(stadt);
        this->strasse = string(strasse);
        this->tel = string(tel);
        anzahl++;
    }
    adresse::adresse(){
        stadt = string("ooooooooooo");
        strasse = string("xxxxxxxxxx");
        tel = string("mmmmmmmmm");
    }
    

    Wenn du schon mit Objekten arbeitest solltest du dir die Initialisierungsleiste angewöhnen (mit char-Arrays geht dies leider nicht). Deine Konstruktoren machen nicht eine Initialisierung sondern im Schlechten Fall 2 Initialisierungen und eine Zuweisung pro Objekt (std::string). Besser:

    adresse::adresse(const char *stadt, const char *strasse, const char *tel)
    :   stadt(stadt);
        strasse(strasse);
        tel(tel);
    {
        ++anzahl; // ++x sollte man x++ vorziehen wenn kein Mißverständis daraus
        // resultieren kann, auch wenn das hier egal ist da es ein integraler
        // datentyp ist, kann es spätestens bei Objekten durchaus messbare
        // Unterschiede geben (++x arbeitet ohne Kopie, x++ mit einer temporären
        // Kopie).
    } // ...
    

    Wie gesagt geht das nicht mit char-Arrays, aber zur Vollständigkeit wollte ich auch auf Fellhuhns Code eingehen.

    cu André



  • asc schrieb:

    Wenn du schon mit Objekten arbeitest solltest du dir die Initialisierungsleiste angewöhnen (mit char-Arrays geht dies leider nicht).

    Finde ich unübersichtlich, verwende ich daher nicht.

    ++anzahl; // ++x sollte man x++ vorziehen wenn kein Mißverständis daraus
    // resultieren kann, auch wenn das hier egal ist da es ein integraler
    // datentyp ist, kann es spätestens bei Objekten durchaus messbare
    // Unterschiede geben (++x arbeitet ohne Kopie, x++ mit einer temporären
    // Kopie).

    Diese Optimierung mute ich bei primitiven Datentypen dem Compiler zu. Ist auch wesentlich leserlicher. Erst die Variable, dann die Operation.



  • Finde ich unübersichtlich, verwende ich daher nicht.

    Diese Begründung ist natürlich wieder der Hammmer -.-
    Hmm gut das dir bis jetzt noch kein Fall aufgekommen ist, wo du es tun musst und du noch wie etwas wirklich optimieren musstest...



  • wie initialisierst du basisklassen? und konstante objekte hattest du auch noch nie in einer klassendefinition?

    übrigens, der code des OP bestätigt wieder einmal, was ich schon seit langem hinter mir her trage:



  • queer_boy schrieb:

    wie initialisierst du basisklassen? und konstante objekte hattest du auch noch nie in einer klassendefinition?

    Die muss ich da wohl gerade in dem Beispiel übersehen haben. 🙄



  • queer_boy: was gefällt dir denn an 'endl' nicht? Schreibst du dort immer '\n'
    und/oder hast du etwas gegen den automatischen flush()-Aufruf. Ich persönlich (sowie anscheinend auch die Entwickler der Standard-Lib) finde es gut, daß jede Zeile geflusht wird.



  • Fellhuhn schrieb:

    queer_boy schrieb:

    wie initialisierst du basisklassen? und konstante objekte hattest du auch noch nie in einer klassendefinition?

    Die muss ich da wohl gerade in dem Beispiel übersehen haben. 🙄

    Es geht nicht um das Beispiel sondern um konsistenz. Und spätestens wenn du C++ professionell einsetzen willst, solltest du die Initialisierungsliste einsetzen. Bei kleinen Anwendungen mag es nicht viel ausmachen, aber bei großen Projekten kann es doch merkbare Unterschiede geben.

    Man soll zwar niemals voreilig Optimierungen machen, das gleiche kann man aber zu wissentlichen Performancebremsen die keinen Mehraufwand (im Falle der Initialisierungsliste ist dies sogar nicht nur Performance, sondern manchmal zwingend) bedeuten sagen.

    cu André



  • @Fellhuhn: Hmm klar ...

    Die muss ich da wohl gerade in dem Beispiel übersehen haben. 🙄

    War nciht im Beispiel vorhanden, doch ein einheitlicher Stil zeugt eher von Professionalität als immer mal was anderes ...



  • (D)Evil schrieb:

    @Fellhuhn: Hmm klar ...

    Die muss ich da wohl gerade in dem Beispiel übersehen haben. 🙄

    War nciht im Beispiel vorhanden, doch ein einheitlicher Stil zeugt eher von Professionalität als immer mal was anderes ...

    Nimmst du dich eigentlich noch ernst?



  • Fellhuhn schrieb:

    Nimmst du dich eigentlich noch ernst?

    Ernstgemeinte Gegenfrage: Hast du vor professionell zu entwickeln? Du musst bedenken das einige hier ihren Lebensunterhalt mit Programmierung verdienen, daher wird es auch in diesem Forum Entwickler geben die versuchen professionell zu arbeiten. Wenn du nur privat vor dich hin wurschtelst brauchst du auf uns nicht zu reagieren - ansonsten werfe ich die Frage mal an dich zurück, und Zweifel an deiner "Ernsthaftigkeit" (bzw. an der herangehensweise an die Programmierung).

    Nicht desto trotz sollte man wenn man anderen hilft lieber den sauberen Stil verwenden.

    cu André



  • Th schrieb:

    queer_boy: was gefällt dir denn an 'endl' nicht? Schreibst du dort immer '\n'
    und/oder hast du etwas gegen den automatischen flush()-Aufruf. Ich persönlich (sowie anscheinend auch die Entwickler der Standard-Lib) finde es gut, daß jede Zeile geflusht wird.

    da die diskussion hier sowieso schon ziemlich off-topic ist - die meiste zeit im standardausgabe-leben benötigt man flushs gar nicht, noch viel weniger oft in kombination mit einem newline. oft ist ein ständiges flushen sogar unerwünscht (in einer zeitkritischen schleife zum beispiel), und die wenigen male, die man es braucht, ist noch dazu std::flush angebrachter (weil auch aussagekräftiger) als std::endl .

    Th schrieb:

    queer_boy: was gefällt dir denn an 'endl' nicht? Schreibst du dort immer '\n'

    ja. die meiste zeit erspart einen das sogar wahnsinnig viel tipparbeit.

    //statt
    cout << "Bitte, bitte, sag etwas..." << endl;
    cout << endl;
    cout << endl;
    //(gesehen so oder so ähnlich in diesem thread)
    //einfacher:
    cout << "Bitte, bitte, sag etwas...\n\n\n";
    

    (abgesehen davon besteht '\n' nur aus vier zeichen, endl im schlimmsten fall aus neun, std::endl aber mindestens aus fünf - aber das tippargument zählt mal nicht)

    das problem ist ähnlich wie bei post- vs. präinkrement. das eine erzeugt einen zusätzlichen effekt, der in der regel nicht gebraucht wird. nur fallen mir weniger tatsächlich notwendige einsätze von endl als von x++ ein. (und das ist der punkt, an dem meine argumentation hängt.)

    und wenn man von anfang an lernt, std::endl für ein newline einzusetzen, kommt eben code raus, wie der oben. und dass dieser code nicht gerade der beste ist (drei-vier unnötige flushs), bekommt doch wohl zustimmung - auch aus gründen der konsistenz (hoppla, das war ja wieder on-topic 😉 ) sollte man daher so weit es geht auf std::endl verzichten.

    Th schrieb:

    und/oder hast du etwas gegen den automatischen flush()-Aufruf. Ich persönlich (sowie anscheinend auch die Entwickler der Standard-Lib) finde es gut, daß jede Zeile geflusht wird.

    die entwickler der standard-lib?
    ich habe nichts gegen einen automatischen flush-aufruf, wenn er gebraucht wird. aber std::endl ruft flush nicht automatisch auf, sondern explizit.
    cin >> var , das ruft flush automatisch auf. das ist gut so.

    für die seltenen fälle, in denen man eine neue zeile nach der ausgabe einer variable haben möchte, habe ich hier auch schon die empfehlung gelesen, sich so etwas zu definieren:

    const char nl = '\n';
    //...
    cout << var << nl;
    

    btw. die empfehlung, auf std::endl zu verzichten, wurde irgendwann vor nicht allzulanger zeit hier im forum auch direkt neben dem post-/präinkrement-gebet gepredigt.

    ich lasse mich natürlich gerne vom gegenteil überzeugen 🙂


Anmelden zum Antworten