Class mit Feldfunktion
-
Da kommt mir noch eine Frage zu vector:
test.clear();
leert den Vector. Aber gibt es wie in meinem Fall auch den Speicher für die Class Elemente frei oder muss ich das irgendwie abfangen?
-
Nathan schrieb:
PS: Deine Funktion ausgabe() schreibt man besser als operator <<, dann kannste direkt schreibe:
std::cout << my_point;Vom << bzw. >> -Operator erwarte ich sicherlich nicht, dass er "ausgabe x/y" schreibt/liest.
Da ist eine Funktion schon in Ordnung. Besser wäre allerdings eine Freie.
-
Aber gibt es wie in meinem Fall auch den Speicher für die Class Elemente frei oder muss ich das irgendwie abfangen?
Den Speicher, den vector selbst alloziert hat, gibt er natürlich immer frei.
Vom << bzw. >> -Operator erwarte ich sicherlich nicht, dass er "ausgabe x/y" schreibt/liest.
Natürlich reduziert man das entsprechend.
int main(int count, char **args)Du musst
main()nicht mit diesen Parametern definieren, wenn du keine Kommandozeilenparameter auswerten willst.
-
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?Edit: sieht ganz danach aus. Wenn ich mal mitzaehle wieoft Konstruktor und Destruktor aufgerufen werden:
#include <iostream> #include <vector> class PUNKT{ public: PUNKT(int px=0, int py=0): x(px),y(py) {++zaehl;} ~PUNKT() {--zaehl;} void verschiebe(int dx, int dy); void ausgabe(); protected: int x,y; static int zaehl; // Anzahl der Elemente }; int PUNKT::zaehl=1; void PUNKT::verschiebe(int dx, int dy) { x=dx; y=dy; } void PUNKT::ausgabe() { std::cout << zaehl << " Punkt " << x << "/" << y << std::endl; } int main(int count, char **args) { std::vector<PUNKT> test; test.push_back(PUNKT(2,3)); test[0].ausgabe(); test.clear(); test[0].ausgabe(); return 0; }Dann brauch ich mir ja keine Sorgen machen.

Du musst main() nicht mit diesen Parametern definieren, wenn du keine Kommandozeilenparameter auswerten willst.
ich weiß wozu der da ist

-
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.
Den Tipp halte ich für Käse.
-
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
newan und zerstört sie mitdelete.deleteruft 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.
-
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.
-
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.
-
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.
-
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?