Klassen als Datenelemente



  • 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.hpp
    

    Main.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 heraus

    MyRectangle.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ückgabetypen Point . 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 man GetUpperLeft() aufgerufen hat.

    Weil GetUpperLeft() const ist, 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


Anmelden zum Antworten