Klassen als Datenelemente
-
Autsch!
// Beginn von Rect.hpp class Point // gehört in die Point.hpp { // Kein Konstruktor, Standardkonstruktor verwenden //Schlecht. Konstruktor macht Kontruktionen doch viel leichter. public: void SetX(int x) { itsX = x; } //Getter UND Setter public? Dann mach doch gleich ne struct void SetY(int y) { itsY = y; } //Getter UND Setter public? Dann mach doch gleich ne struct int GetX()const { return itsX;} //Getter UND Setter public? Dann mach doch gleich ne struct int GetY()const { return itsY;} //Getter UND Setter public? Dann mach doch gleich ne struct private: //aber hier private, helau! int itsX; int itsY; }; // Ende der Klassendeklaration von Point class Rectangle { public: Rectangle (int top, int left, int bottom, int right);//ok ~Rectangle () {} //nutzlos int GetTop() const { return itsTop; } //alle vier nutzlos int GetLeft() const { return itsLeft; } int GetBottom() const { return itsBottom; } int GetRight() const { return itsRight; } Point GetUpperLeft() const { return itsUpperLeft; } //alle vier schlecht Point GetLowerLeft() const { return itsLowerLeft; } Point GetUpperRight() const { return itsUpperRight; } Point GetLowerRight() const { return itsLowerRight; } void SetUpperLeft(Point Location) {itsUpperLeft = Location;} //alle vier nutzlos void SetLowerLeft(Point Location) {itsLowerLeft = Location;} void SetUpperRight(Point Location) {itsUpperRight = Location;} void SetLowerRight(Point Location) {itsLowerRight = Location;} void SetTop(int top) { itsTop = top; } //alle vier schlecht void SetLeft (int left) { itsLeft = left; } void SetBottom (int bottom) { itsBottom = bottom; } void SetRight (int right) { itsRight = right; } int GetArea() const; //braucht man das? private: Point itsUpperLeft; //alle vier extrem schei Point itsUpperRight; Point itsLowerLeft; Point itsLowerRight; int itsTop; //die hier reichen, die expunkte können immer "berechnet" werden int itsLeft; int itsBottom; int itsRight; }; // Ende von Rect.hpp[/cpp]
-
Was Pumuckl sagt ist richtig problematisch. Denn dieses mehrfache halten der einzelnen Daten birgt wahnsinniges Fehlerpotential, und die Klasse macht richtig gut Gebrauch von den Fehlern!
z.B.:void SetUpperLeft(Point Location) {itsUpperLeft = Location;}Hier wird nur ein neuer Punkt für links oben gesetzt. Ignoriert werden top, left und topRight. Denn für all diese Werte wird dich auch etwas ändern.
Oder aber die Klasse modelliert kein Rechteck sondern ein Viereck, und auch da gibt es Fehler in der Implementierung, z.B. die GetArea sieht sicher nicht mehr so leicht aus. Denn für ein beliebiges Viereck gilt nicht mehr flaeche = hoehe*breite.Ein Rechteck wird definiert durch zwei Punkte, die auf einer der Diagonalen liegen, also z.B. topLeft und bottomRight. Mehr Member braucht die Klasse Rectangle nicht. Daraus bekommt man alle Infos.
Beim Setzen von einer der Ecken muss man halt aufpassen, ob sich z.B. bottomRight in bottomLeft ändert, wenn man ein neues topLeft setzt, welches aber ein p.x > bottomRight.x hat.Langer Rede kurzer Sinn, wenn das 1:1 aus dem Buch abgeschrieben ist, würde ich das dem Verlag zurückschicken
Denn solche hammer logischen Fehler gehören nicht in ein Buch...
-
@Volkard
Und was haben sich die Qt Leute dabei gedacht? Getter, Setter UND Referenz!
http://doc.trolltech.com/4.3/qpoint.html
Ist es vielleicht doch nur geschmackssache ob man das Zeug public macht oder nicht unabdingbare Funktionen einbaut?
-
Also, da die Frage war, was das genau ist, und nicht, warum es ziemlich schlecht gemacht ist, fasse ich mal kurz zusammen:
Klasse Punkt:
- X- und Y-Wert (int)
- Getter und Setter für X- und Y-Wert (Funktionen, über die man den Wert erfahren und zuweisen kann, da die eigentlichen Variablen ja private sind (dass das allerdings keinen Sinn macht, wurde ja schon gesagt))Klasse Rechteck:
- 4 Objekte der Klasse Punkt, die die vier Eckpunkte darstellen sollen.
- Werte für oben unten rechts und links
- Getter und Setter für alle Eigenschaften.Das Buch würde ich übrigens verbrennen. Wenn das so da drin steht, ist es nicht nur veraltet sondern auch schlecht.

-
wx++ schrieb:
Klasse Punkt:
- X- und Y-Wert (int)
- Getter und Setter für X- und Y-Wert (Funktionen, über die man den Wert erfahren und zuweisen kann, da die eigentlichen Variablen ja private sind (dass das allerdings keinen Sinn macht, wurde ja schon gesagt))Und fehlender Point-Konstruktor.
Den braucht man.Point Rectangle::getTopLeft() { return Point(left,top); }die andere version mit Point-Anlegen, Daten-Reinschreiben, return will glaub ich keiner haben.
-
Hossenscheisser schrieb:
@Volkard
Und was haben sich die Qt Leute dabei gedacht? Getter, Setter UND Referenz!
http://doc.trolltech.com/4.3/qpoint.html
Ist es vielleicht doch nur geschmackssache ob man das Zeug public macht oder nicht unabdingbare Funktionen einbaut?
Vielleicht haben die Leute nur zu viel Kaffe getrunken. Das vermag ich nicht zu beurteilen.
-
volkard schrieb:
Hossenscheisser schrieb:
@Volkard
Und was haben sich die Qt Leute dabei gedacht? Getter, Setter UND Referenz!
http://doc.trolltech.com/4.3/qpoint.html
Ist es vielleicht doch nur geschmackssache ob man das Zeug public macht oder nicht unabdingbare Funktionen einbaut?
Vielleicht haben die Leute nur zu viel Kaffe getrunken. Das vermag ich nicht zu beurteilen.
Ich mache es ehrlich gesagt auch ganz gerne so, weil durch setter/getter kannst du später gut erweitern (auch wenn er am Anfang noch leer ist) ohne 500mio punkt.x in punkt.getX() umbenennen zu müssen ...
Zudem ist sind Referenzen ganz nett, wenn du sowas machen willst:template<typename Typ> class liste { Typ* anfang; //den rest kennst du ja... } class wurstkuchen //bla ... class apfelblutsuppe : public wurstkuchen //bla ... class basis { liste<wurstkuchen> m_liste; public: liste<wurstkuchen>& liste() { return m_liste; } }; class derivat { //Unter vorraussetzung dass factory auch apfelblutsuppe herstellt: liste<apfelblutsuppe>& liste() { return *( (liste<apfelblutsuppe>*)(&liste<wurstkuchen>) ); } };Nur wie man richtig castet weiß ich noch nicht. :p
Bitte zerlege es wenn du dich dazu veranlasst siehst!

-
volkard schrieb:
Hossenscheisser schrieb:
@Volkard
Und was haben sich die Qt Leute dabei gedacht? Getter, Setter UND Referenz!
http://doc.trolltech.com/4.3/qpoint.html
Ist es vielleicht doch nur geschmackssache ob man das Zeug public macht oder nicht unabdingbare Funktionen einbaut?
Vielleicht haben die Leute nur zu viel Kaffe getrunken. Das vermag ich nicht zu beurteilen.
Nö, die wollen einfach binärkompatibel bleiben. Und Hinzufügen von Membern bricht die Binärkompatibilität. Drum setzen die Qtsoftwareler über die ganze Bibliothek hinweg auf Pimpl. Und das geht schlecht mit einem struct, der in so vielen Bereichen des Frameworks auftaucht.
-
Kumpane schrieb:
volkard schrieb:
Hossenscheisser schrieb:
@Volkard
Und was haben sich die Qt Leute dabei gedacht? Getter, Setter UND Referenz!
http://doc.trolltech.com/4.3/qpoint.html
Ist es vielleicht doch nur geschmackssache ob man das Zeug public macht oder nicht unabdingbare Funktionen einbaut?
Vielleicht haben die Leute nur zu viel Kaffe getrunken. Das vermag ich nicht zu beurteilen.
Nö, die wollen einfach binärkompatibel bleiben. Und Hinzufügen von Membern bricht die Binärkompatibilität. Drum setzen die Qtsoftwareler über die ganze Bibliothek hinweg auf Pimpl. Und das geht schlecht mit einem struct, der in so vielen Bereichen des Frameworks auftaucht.
Wie ist Binärkompatibilität denn in diesem Zusammenhang zu verstehen?

-
Samsn schrieb:
Wie ist Binärkompatibilität denn in diesem Zusammenhang zu verstehen?

Weil wenn irgendwann einem einfällt, eine QPoint-Klasse braucht ein neues Member element, dann ändert das Hinzufügen die ABI. Programme, die mit der alten Version kompiliert wurden, sind dann nicht mehr lauffähig. Es ist einfach Vorsicht und Voraussicht. Man findet in dem Qt-Framework öffentlich zugänglich nur Klassen, keine Structs.
Meiner Info nach gab es nur ein einziges Mal Probleme mit ABI-Änderungen, das war nur auf Mac, um Widgets auf GraphicsView zu ermöglichen. Diese Sturheit hat sich also bezahlt gemacht

-
Vielen Dank für diese überaus vielen Antworten, ich bin überwältigt, auch wenn ich einige Sachen noch nicht ganz nachvollziehen kann was es jetzt mit Qt auf sich hat. Aber ich denke anhand der vielen Kommentare werde ich es schaffen^^.
Vielen Dank für eure enorme Hilfe.
Mickes
-
Das mit Qt hatte jetzt nichts konkret mit dir zu tun.
-
Übrigens habe dieses Buch auch als Ebook gefunden und die Sache mit den Klassen steht hier: http://www.informit.de/books/c++21/data/kap06.htm#76988 , das ganze Buch unter http://www.informit.de/books/c++21/data/start.htm
-
Und vielen Dank an Volkard, dass er den Source dokumentiert hat. Durch das streichen von noch einem Viererblock macht die Sache jetzt einen Sinn. Hatte mich da ziehmlich verwirren lassen durch die Zeilen, die nichts im Programm zu suchen haben.
-
Resume betrachtet lautet der Source ja dann:
Rect.hpp
#include <iostream> using namespace std; class Point // nimmt X,Y-Koordinaten auf { // Kein Konstruktor, Standardkonstruktor verwenden public: void SetX(int x) { itsX = x; } void SetY(int y) { itsY = y; } int GetX()const { return itsX;} int GetY()const { return itsY;} private: int itsX; int itsY; }; // Ende der Klassendeklaration von Point class Rectangle { public: Rectangle (int top, int left, int bottom, int right); ~Rectangle () {} Point GetUpperLeft() const { return itsUpperLeft; } Point GetLowerLeft() const { return itsLowerLeft; } Point GetUpperRight() const { return itsUpperRight; } Point GetLowerRight() const { return itsLowerRight; } void SetTop(int top) { itsTop = top; } void SetLeft (int left) { itsLeft = left; } void SetBottom (int bottom) { itsBottom = bottom; } void SetRight (int right) { itsRight = right; } int GetArea() const; private: Point itsUpperLeft; Point itsUpperRight; Point itsLowerLeft; Point itsLowerRight; int itsTop; int itsLeft; int itsBottom; int itsRight; }; // Ende von Rect.hppMain.cpp
#include "rect.hpp" Rectangle::Rectangle(int top, int left, int bottom, int right) { itsTop = top; itsLeft = left; itsBottom = bottom; itsRight = right; itsUpperLeft.SetX(left); itsUpperLeft.SetY(top); itsUpperRight.SetX(right); itsUpperRight.SetY(top); itsLowerLeft.SetX(left); itsLowerLeft.SetY(bottom); itsLowerRight.SetX(right); itsLowerRight.SetY(bottom); } // Rechteckfläche berechnen. Dazu Ecken bestimmen, // Breite und Höhe ermitteln, dann multiplizieren. int Rectangle::GetArea() const { int Width = itsRight-itsLeft; int Height = itsTop - itsBottom; return (Width * Height); } int main() { // Eine lokale Rectangle-Variable initialisieren Rectangle MyRectangle (100, 20, 50, 80 ); int Area = MyRectangle.GetArea(); cout << "Flaeche: " << Area << "\n"; cout << "Obere linke X-Koordinate: "; cout << MyRectangle.GetUpperLeft().GetX(); return 0;Wenn ich es richtig sehe, werden in Klasse 2 vier Instanzen "itsUpperLeft, itsUpperRight..." angelegt. Die einzelnen x,y Punkte werden durch die Rectangel-Instanz in main initialisiert und später kann man in main mit
MyRectangle.GetUpperLeft().GetX()die Sachen wieder abrufen.
Was mir noch Fragen auf gibt ist die Zeile
Point GetUpperLeft() const { return itsUpperLeft; }.
Was passiert in dieser Zeile? Wirde da ein interner Zeiger auf die Instanz itsUpperLeft zurückgegeben, da ich sonst ja nicht drauf zu greifen kann da sie privat ist? Und warum steht dann selber Point davor? Es sieht aus wie eine eigene Instanz GetUpperLeft(), aber es ist ja eine Funktion

Und warum kann ich nicht aus main herausMyRectangle.GetUpperLeft().SetX()schreiben und mit
MyRectangle.GetUpperLeft().GetX()wieder abrufen, da kommt Müll raus?
Vieleicht kann da noch mal jemand etwas zu sagen
.Vielen Dank
Mickes
-
GetUpperLeft()hat den RückgabetypenPoint. Da dort weder ein * noch ein & vorhanden ist (also weder Zeiger noch Referenz), wird die Instanz kopiert. Das impliziert natürlich, dass du beim Zugriff nicht mehr auf die linke obere Ecke der Klasse selbst zugreifst, sondern auf eine Kopie davon. Dadurch haben Änderungen daran keinen Effekt auf das ursprüngliche Objekt, bei dem manGetUpperLeft()aufgerufen hat.Weil
GetUpperLeft()constist, sieht man auch, dass man über den Aufruf dieser Memberfunktion das Objekt nicht verändern kann.Um direkt auf dem Objekt zu arbeiten, kannst du Referenzen zurückgeben, allerdings darf die Memberfunktion dann nicht mehr
const-qualifiziert sein.
-
So, habe mir jetzt auf Ebay das Buch C++ Primer, Aufl. 2007 für 10 Euro ersteigert und fange die Sache nochmal von Vorne an. Das Buch C++ in 21 Tagen werde ich als Erfahrungswert in die Ablage legen. Denke das macht Sinn. Trotzdem, vielen Dank für eure Hilfe.
Gruß
Mickes