Class mit Feldfunktion



  • Jockelx schrieb:

    Sone schrieb:

    Vom << bzw. >> -Operator erwarte ich sicherlich nicht, dass er "ausgabe x/y" schreibt/liest.

    Natürlich reduziert man das entsprechend.

    🙄
    Hauptsache irgendwie auf 1000 Beiträge pro Tag kommen...
    Er schreibt eine Funktion, die irgendwas wie "Punkt x/y" auf der Konsole ausgeben soll und kriegt als Tipp, dass er dafür den Shift-Operator überschreiben soll.

    Nicht shift: den ostream operator <<, der es einem ermöglicht Dinge auf ostreams auszugeben!



  • Ja, das ist mir klar.

    Was war dann deine Frage?

    Ruft er dann auch den Destruktor der Klasse automatisch auf?

    Natürlich!? Er legt die Elemente standardmäßig mit new an und zerstört sie mit delete . delete ruft natürlich den Destruktor auf.

    Hauptsache irgendwie auf 1000 Beiträge pro Tag kommen...

    Schweig, wenn du nicht angemessener reden kannst.

    Er schreibt eine Funktion, die irgendwas wie "Punkt x/y" auf der Konsole ausgeben soll und kriegt als Tipp, dass er dafür den Shift-Operator überschreiben soll.

    Erstens ist es eine sie, zweitens kann man den Shift-Operator überladen um die Zahlen auszugeben und anschließend eine Funktion die davor noch einen String ausgibt.

    Und überhaupt wäre der standardmäßige Tipp, innerhalb der zuständigen Funktion überhaupt nichts zu beschreiben, sondern eben nur die Zahlen auszugeben. Dafür hast du aber natürlich nicht weit genug gedacht, da du nur beschäftigt warst zu nörgeln.

    Nicht shift: den ostream operator <<,

    Das ist der Shift-Operator, so nennt man ihn.


  • Mod

    Lymogry schrieb:

    Sone schrieb:

    Den Speicher, den vector selbst alloziert hat, gibt er natürlich immer frei.

    Ja, das ist mir klar.
    Ruft er dann auch den Destruktor der Klasse automatisch auf?

    Neben deinen eigenen Experimenten noch die Bestätigung: Ja, tut er. Der vector ist, so wie die anderen Standardcontainer, ein Rundum-Sorglos-Paket, mit korrektem Erzeugen, Kopieren und Zerstören. Im Falle des vector ist das ein (recht dicker) Wrapper um ein manuelles new/delete-Paar. new und delete erzeugen und zerstören Objekte vollständig.

    Falls es dich interessiert, wie man selber solche Klassen wie den vector schreibt (dein PUNKT ist in dieser Hinsicht nämlich nicht korrekt!), die Stichworte dazu sind: RAII und die Regeln der Großen 3 (neuerdings 5). Wieso dein PUNKT nicht korrekt ist:
    https://ideone.com/Qrj8uj
    Ich habe mal ein paar mehr Objekte in den Vector gepackt. Die resultierende negative Zahl ist kein Fehler im vector, sondern kommt daher, dass deine Testklasse die Regel der Großen 3 nicht beachtet.

    So ist es richtig:
    https://ideone.com/ut2UKt
    Neben einigen Detailsverbesserungen und Fehlerkorrekturen (am Anfang hast du 0 Punkte, nicht 1!) geht es vor allem um den Kopierkonstruktor.



  • Was ist denn das, SeppJ:

    test.clear();
    test[0].ausgabe();
    

    Das solltest du noch korrigieren.


  • Mod

    Sone schrieb:

    Was ist denn das, SeppJ:

    test.clear();
    test[0].ausgabe();
    

    Das solltest du noch korrigieren.

    Habe ich doch! Das erste ist noch das Originalprogramm, bloß mit mehr Punkten.

    edit: Als Referenz für den Threadersteller, damit er nicht Zeile für Zeile vergleichen braucht:
    - Kopierkonstruktor eingefügt
    - ausgabe static gemacht, so dass man kein Objekt zur Ausgabe des statischen Zählers braucht
    - private statt protected. Der Nutzen von protected ist nur recht beschränkt. Hier ist sicherlich kein Anwendungsszenario dafür. Auch wenn ich weiß, dass man als Anfänger gerne alles protected macht: Wenn du etwas protected machst, kannst du es von der Kapselung her auch gleich public machen. protected brauchst du nur in Szenarien, wo der ganze Zweck deiner Klasse ist, dass man von ihr erbt.
    -'\n' statt endl. endl ist '\n' + flush. Ich will hier nicht flushen. Auch sonst will ich praktisch nie die Ausgabe flushen, außer als Prompt vor einer Eingabe. Und dann geschieht das ohnehin schon automatisch.
    -Die main den Änderungen in der Klasse angepasst. Beachte, dass nun nicht mehr auf nicht-existierende Elemente zugegriffen wird (dass, das Sone meinte. Nach dem clear gibt es kein 0'tes Element mehr!).



  • SeppJ schrieb:

    Habe ich doch!

    Oh? Ich bin sicher, ich sah bei deiner korrigierten Variante dasselbe. Ja, bei dir ist es eine statische Funktion.



  • Danke schonmal für die Korrekturen Sepp!

    hmm hmm ... ich versuche das mit dem Kopierkonstruktor gerade nachzuvollziehen: http://de.wikipedia.org/wiki/Dreierregel
    "Wird das für eine dieser Elemente gemacht, so bedeutet das, dass die compilergenerierte Version des entsprechenden Elements den Anforderungen der Klasse nicht genügt."
    Wenn ich auf einen expliziten Destruktor verzichte, brauche ich diese Regeln nicht zu. Ich hab in dem Beispiel den Destruktor nur mal zum Zählen miteingebaut.

    Ist es denn ok, wenn das Program den Vector leert (mit dem default Destruktor) und ich global den zaehler wieder auf 0 setze. Bekomme ich da auch Probleme mit?

    Ich lerne hier sehr viel! Vielen Dank an alle! 🙂



  • Wenn ich auf einen expliziten Destruktor verzichte, brauche ich diese Regeln nicht zu.

    ... befolgen? Nein, das brauchst du nicht. Das heißt, dass alle Kopier-Operationen auch vom Compiler generiert werden können.

    Ist es denn ok, wenn das Program den Vector leert (mit dem default Destruktor) und ich global den zaehler wieder auf 0 setze. Bekomme ich da auch Probleme mit?

    Welcher Zähler? Nein, damit bekommst du keine Probleme.


  • Mod

    Lymogry schrieb:

    Wenn ich auf einen expliziten Destruktor verzichte, brauche ich diese Regeln nicht zu. Ich hab in dem Beispiel den Destruktor nur mal zum Zählen miteingebaut.

    Die Dreierregel brauchst du hier ausdrücklich nur wegen dem Zähler. Da du für den Zähler korrekterweise einen Destruktor brauchst, brauchst du hier auch einen Kopierkonstruktor, damit Kopien (und der vector macht Kopien!) korrekt gezählt werden. Bei deiner PUNKT-Klasse, wie sie eigentlich geplant ist, brauchst du weder einen eigenen Destruktor noch Kopierkonstruktor.

    Ist es denn ok, wenn das Program den Vector leert (mit dem default Destruktor) und ich global den zaehler wieder auf 0 setze. Bekomme ich da auch Probleme mit?

    Ja, aber wozu ist der Zähler dann noch gut?



  • Aha! 🙂

    Gut, dann noch ein paar Fragen zu deinen Korrekturen: 😉

    #include <iostream> 	
    #include <vector>
    
    class PUNKT{
    public:
    	PUNKT(int px=0, int py=0): x(px),y(py) {++zaehl;}				// Konstruktor 
    	PUNKT(const PUNKT& other): x(other.x),y(other.y) {++zaehl;}		// Kopierkonstruktor
    	~PUNKT() {--zaehl;}												// Destruktor 
    								// wo ist der Zuweisungsoperator aus der Dreierregel?? 
    	void verschiebe(int dx, int dy);
    	void ausgabe();
    private:										
    	int x,y;
    	static int zaehl;		// Anzahl der Elemente 
    };
    
    int PUNKT::zaehl=0; 
    
    void PUNKT::verschiebe(int dx, int dy) {
    	x=dx;
    	y=dy;
    }
    
    void PUNKT::ausgabe() {	 			// static für private Dateien??
    	std::cout << zaehl << " Punkt " << x << '/' << y << '\n';	
    }
    
    int main(int count, char **args) {
    
    	std::vector<PUNKT> test;
    	test.push_back(PUNKT(2,3));
    	test.push_back(PUNKT(1,1));
    	test.push_back(PUNKT(2,6));
    	test[0].ausgabe();
    	test.clear();
    	test.push_back(PUNKT(5,5));
    	test[0].ausgabe();
    
    	return 0;
    }
    

    http://de.wikipedia.org/wiki/Dreierregel

    Oder ist mit dem Zuweisungsoperator (int px=0, int py=0) aus dem Konstruktor gemeint?



  • Mit dem Zuweisungsoperator ist der überladene (Kopier-)Zuweisungsoperator der Klasse gemeint:

    class PUNKT {
       ...
       PUNKT& operator=(const PUNKT&);
       ...
    };
    

    Die Dreierregel ist im Übrigen nur eine Faustregel. Und hier ist kein selbstdefinierter Zuweisungsoperator notwendig, weil sich die Anzahl der Objekte bei einer Zuweisung nicht ändert.


  • Mod

    Ja, war didaktisch wohl ein bisschen ungünstig, die Dreierregel an dem einen Beispiel zu erklären, wo man wirklich nur zwei von den dreien braucht 🙂 . Der Instanzenzähler ist einer der ganz wenigen Fälle, in denen die Dreierregeln nicht komplett eingehalten werden muss.



  • Ein klassisches, abstraktes Beispiel: Ich habe einen Zeiger auf eine Ressource als Member. Die Ressource muss freigegeben werden, nachdem sie im Konstruktor erzeugt wurde, und die Klasse muss die Ressource bei Kopien auch kopieren.
    Typisches RAII bzw. Regel der großen Drei.

    static für private Dateien??

    Ja, die Sichtbarkeit dehnt sich auf alles aus, was in einer Klasse überhaupt deklariert werden kann.



  • Sone, ich finds ja großartig, dass du dich hier einbringen willst, aber irgendwie scheinst du nicht alles mitzulesen. 😉



  • Lymogry schrieb:

    irgendwie scheinst du nicht alles mitzulesen

    Eigentlich war dein Kommentar im Code völlig sinnlos, ich musste also raten, was du meinst.
    Also: Was meintest du mit deinem Kommentar? Oder was genau war an meinem Post nicht dem Kontext entsprechend?



  • Ist ja süß, jetzt ist er eingeschnappt 😉

    Lass es gut sein oder philosophier noch etwas. Tipp: Was der Zähler ist, das hast du nach 3 Seiten noch nicht begriffen. Was soll ich dann noch mit deinen sogenannten Tipps oder dem abstrakten Beispiel? 🕶

    @SeppJ
    DANKE! Du hast mir viel geholfen. 🙂

    EDIT: nach dem fünftmaligen Editieren ist er wohl nicht mehr eingeschnappt. 🙂 Oder doch?



  • Oder doch?

    Nein, ich kann mich beherrschen.

    Was der Zähler ist, das hast du nach 3 Seiten noch nicht begriffen.

    Bitte? Natürlich habe ich das!? Ich schrieb "Welcher Zähler" als Anspielung, da du den Zähler ja offensichtlich rausschmeißen wirst, wenn der Destruktor wieder leer ist. Woran erkennst du das?



  • .. so langsam interessiert mich dein Alter. 😃 Frag lieber nicht: wieso!



  • So, jetzt reicht es mir. Solche unsachlichen Diskussionen tue ich mir nicht an.



  • Lymogry schrieb:

    .. so langsam interessiert mich dein Alter. 😃 Frag lieber nicht: wieso!

    Der Einzige, der sich hier kindisch benimmt, bist du. Nebst deiner schwachen Zeichensetzung ist besonders dein überheblicher Stil ein Dorn im Auge. Daher:

    Solche unsachlichen Diskussionen tue ich mir nicht an.


Anmelden zum Antworten