Klassen in C++ Neuling versteht es nicht :(



  • Hi @ all

    Habe kürzlich angefangen c++ zu lernen.
    Nun hab ich mir ein Buch besorgt (c++ in 21 Tagen) und legte los.
    Da ich schon ein bisschen (nur wenig) Erfahrung mit Basic habe fielen mir die ersten Kapitel, bei denen es um Funktionen und Variablen ging nicht sehr schwer.

    Nun kam ich zum Thema Klassen und dachte schon ich hätte das Prinzip verstanden.

    Nun kam folgender Code im Buch, den ich trotz Erklärung im Buch einfach nicht ganz verstand:

    // Beginn von Rect.hpp
    #include <iostream.h>
    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 () {}
    
    int GetTop() const { return itsTop; }
    int GetLeft() const { return itsLeft; }
    int GetBottom() const { return itsBottom; }
    int GetRight() const { return itsRight; }
    
    Point GetUpperLeft() const [b]{ return itsUpperLeft; }[/b]
    Point GetLowerLeft() const [b]{ return itsLowerLeft; }[/b]
    Point GetUpperRight() const [b]{ return itsUpperRight; }[/b]
    Point GetLowerRight() const [b]{ return itsLowerRight; }
    [/b]
    void SetUpperLeft[b](Point Location) {itsUpperLeft = Location;}[/b]
    void SetLowerLeft[b](Point Location) {itsLowerLeft = Location;}[/b]
    void SetUpperRight[b](Point Location) {itsUpperRight = Location;}[/b]
    void SetLowerRight[b](Point Location) {itsLowerRight = Location;}[/b]
    
    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
    
    // Beginn von rect.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);
    }
    // Rechteckflaeche berechnen. Dazu Ecken bestimmen,
    // Breite und Hoehe 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;
    }
    

    Als ich den Code gesehen habe, ist mir erstmal schlecht geworden.

    Nach reiflichem Überlegen habe ich schon Licht im Tunnel gesehen.

    Nun meine Fragen zum markiertem Bereich:

    Point GetUpperLeft() const { return itsUpperLeft; }:
    soweit ich das verstanden habe ist der Rückgabewert ein Objekt der Klasse Point? Das ergibt doch keinen Sinn oder?

    void SetUpperLeft**(Point Location) {itsUpperLeft = Location;}**:
    Point Location ist ein Objekt. Und das dann als Parameter? Welchen Wert soll itsUpperLeft jetzt annehmen
    Ein Objekt der Klasse Point hat doch 2 Parameter (x und y) die man über die Funktion setX und setY setzen kann.
    theoretissch müsste ich doch dann über das Objekt MyRectangle.GetUpperLeft(hier x und y) eingeben können?

    Kurzum ich bin verwirrt 😕 😕 😕

    Bitte fühlt euch nicht von meinem langen Text erschlagen.

    Ich hoff ihr könnt mir helfen. währe echt dankbar wenn ihr mir erklären könntet was das zu bedeuten hat 🙂

    Danke im vorraus



  • Wie bei der Klasse Point nachzulesen ist:

    // Kein Konstruktor, Standardkonstruktor verwenden

    Dies bedeutet, daß der Compiler automatisch einen Standard-Konstruktor sowie (was noch im Kommentar fehlt) einen Kopier-Konstruktor anlegt:

    Point::Point(); // Standard-Konstruktor
    Point::Point(const Point &point); // Kopier-Konstruktor
    

    Der automatisch erzeugte Kopier-Konstruktor kopiert einfach jeden Member der Klasse (entsprechend dessen Kopier-Konstruktor).

    D.h. es wird immer ein gesamtes Objekt der Klasse Point (d.h. die Member itsX und itsY) zurückgegeben bzw. gesetzt.

    Du kannst jetzt mit den Objekten dieser Klasse(n) genauso verfahren wie mit den eingebauten Datentypen (bool, int, short, long, float, double, ...).
    Solche Klassen nennt man "Konkrete Klassen".



  • Das Buch scheint auch sehr schlecht zu sein, wenn DAS zur Einführung von Klassen gehört. DAS kann auch kein Anfänger verstehen! Und es ist verständlich das die dabei übel wird.

    Die "In 21 Tagen lerne XZY"-Reihe ist generell nicht zu empfehlen!

    Buchempfehlung: http://www.oop-mit-cpp.de



  • Point GetUpperLeft() const { return itsUpperLeft; }:
    soweit ich das verstanden habe ist der Rückgabewert ein Objekt der Klasse Point? Das ergibt doch keinen Sinn oder?

    Ja, der Rückgabewert ist ein Objekt der Klasse Point. Und doch, es macht Sinn. Man soll ja die Daten einer Klasse verarbeiten können. Und ein Rechteck besteht ja aus 4 Punkten. Also kann man hier jeden Punkt einzeln abfragen und setzen. So macht man das in jeder OOP-Sprache (Java als Bsp., nennt man Getter und Setter) Allerdings würde ich eine const-Referenz zurückgeben. Hier wird momentan das komplette Objekt kopiert. Eine Referenz ist nicht das komplette Objekt, sondern nur ein Verweis auf das Objekt. const deshalb, damit man es nicht verändern kann. Aber das mit der Referenz kannst erstmal ignorieren ;).

    const Point& GetUpperLeft() const { return itsUpperLeft; }
    

    void SetUpperLeft(Point Location) {itsUpperLeft = Location;}:
    Point Location ist ein Objekt. Und das dann als Parameter? Welchen Wert soll itsUpperLeft jetzt annehmen
    Ein Objekt der Klasse Point hat doch 2 Parameter (x und y) die man über die Funktion setX und setY setzen kann.
    theoretissch müsste ich doch dann über das Objekt MyRectangle.GetUpperLeft(hier x und y) eingeben können?

    Du meinst sicherlich SetUpperLeft :). Get hat ja keine Parameter.
    Könntest du fast so machen, wenn du folgendes zur Klasse Point hinzufügst:

    class Point
    {
       Point (int x, int y) { itsX = x; itsY = y; }
    (...)
    };
    // Damit geht das dann wie folgt:
    MyRectangle.SetUpperLeft(Point(X, Y));
    

    Ein weitere Möglichkeit wäre die Klasse myRectangle wie folgt zu ändern:

    class Rectangle
    {
    (...)
    void SetUpperLeft(int x, int y) 
    {
       itsUpperLeft.SetX(x); itsUpperLeft.SetY(y);
    }
    (...)
    };
    

    Wenn noch Fragen da sind, raus damit.
    rya.



  • Danke für eure bisherigen Antworten

    Yep ich meinte SetUpperLeft 🙂

    So...

    Point GetUpperLeft() const { return itsUpperLeft; }
    

    Das heißt ich bekomme mit der Rectangle Methode "GetUpperLeft()" die einen Rückgabewert vom Typ Point hat immer ein ganzens Objekt (itsUpperLeft), also immer 2 Werte (itsX und itsY) automatisch zurück, ohne das ich irgendwie über die Zugriffsmethode (GetX und GetY) der Point Klasse gehen muß?
    Versteh ich das richtig?

    Hier werden ja die Koordinaten über die Zugriffsmethode gesetzt:

    itsUpperLeft.SetX(left); 
    itsUpperLeft.SetY(top);
    

    Muss man sie nicht gleichermaßen abfragen?

    ------------------------------

    void SetUpperLeft(Point Location) {itsUpperLeft = Location;}
    

    und das Objekt Location der Klasse Point beinhaltet demnach ebenfalls automatisch 2 Werte (itsX und itsY) die sie an das Objekt itsUpperLeft der Klasse Rectangle übergibt.

    Ich verstehe nicht worher mein Programm weiß, das das Objekt Location 2 Werte beinhaltet und das Objekt itsUpperLeft 2 Werte erwartet?
    Weiß mein Compiler es weil ich 2 Member für die Klasse Point definiert habe?

    Danke nochmals für die Mühe die ihr euch macht.

    P.S. @ Artchi:
    eigentlich war ich mit dem Buch bisher ganz zufrieden. Nun lässt es mich
    irgendwie schon im Regen stehen. Werde mir mal den Buchvorschlag anschauen.
    Es war übrigens nicht ganz die Einführung. Im Buch behandelte man vorher
    noch ein anderes Beispiel (Die Klasse Cat und die Katze Frisky), welches
    ich auch verstanden habe. 🙂



  • Das heißt ich bekomme mit der Rectangle Methode "GetUpperLeft()" die einen Rückgabewert vom Typ Point hat immer ein ganzens Objekt (itsUpperLeft), also immer 2 Werte (itsX und itsY) automatisch zurück, ohne das ich irgendwie über die Zugriffsmethode (GetX und GetY) der Point Klasse gehen muß?

    Richtig. Es ist immer ein ganzes Objekt. Allerdings eine Kopie davon. Das heisst, du kannst das Objekt in der Klasse Rectangle über diese Rückgabe-Methode nicht verändern. GetX() und GetY() musst du nur verwenden, wenn du an die Daten ran willst. Denn damit erfährst du sie.

    Muss man sie nicht gleichermaßen abfragen?

    Was meinst du damit? Zum Abfragen hast ja die GetX() und GetY() Methode.

    Ich verstehe nicht worher mein Programm weiß, das das Objekt Location 2 Werte beinhaltet und das Objekt itsUpperLeft 2 Werte erwartet?
    Weiß mein Compiler es weil ich 2 Member für die Klasse Point definiert habe?

    Jup.
    Genau deswegen.



  • ich denke ich habe es jetzt verstanden 🙂
    bekomme ich durch diesen Code dann itsX und itsY für myRectangle angezeigt:

    cout << myRectangle.GetUpperLeft();
    

    Vorrausgesetzt ich habe die beiden Werte vorher definiert.



  • Nein, so einfach isses dann doch nicht. GetUpperLeft gibt ja ein Objekt des Typs Point zurück und cout weiss nicht, wie er das ausgeben soll.

    std::cout << rectangle.GetUpperLeft().GetY() << "/" << rectangle.GetUpperLeft().GetZ();
    

    So wäre das richtig in dem Fall. Oder du definierst einen operator um das Objekt Textmäßig darstellen zu können. Aber das wäre denke ich momentan noch zuviel ;).
    rya.

    ps.: Wenns dich wirklch interessiert...

    class Point
    {
    (...)
    friend ostream& operator <<(ostream &os,const Point& obj);
    };
    
    ostream& operator <<(ostream &os,const Point& obj)
    {
       os << obj.GetX() << "/" << obj.GetY();
       return os;
    }
    


  • ok danke

    habe es nun endlich kapiert (denke ich :)).

    Danke für deine Mühe.



  • darf heute eigentlich schon jeder heizungsinstallateur bücher über c++ schreiben? der code ist ja der blanke horror.


Anmelden zum Antworten