Seite 1 von 2 12 Letzte »
Ergebnis 1 bis 20 von 36

Fragen zu C++ (aus Softwarefragen und -probleme)

  1. #1 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    Hallo, wie im Titel steht habe ich ein paar Fragen zu C++ was wir im Rahmen eines Faches im Studium verstehen lernen sollen.
    Im Prinzip stellt sich nicht die Frage, wie viel Sinn unsere Programme ergeben, wir sollen vor allem die Funktionen beherrschen und uns mit den Leuten die das dann beruflich machen verständigen können und zumindest nen Überblick haben können, was da programmiert wird. Informatik oder in dem Fall OOP ist auch nicht mein Hauptstudium, also kann ich echt nicht viel Vorwissen vorweisen, darum wären manche Fragen sicher auch nicht wirklich fundiert wobei ich auf Nachsehen hoffe.
    Aber anstatt direkt mit meinem Problem loszulegen frage ich lieber erstmal ob mir hier prinzipiell geholfen werden kann oder ob das nicht vllt verschoben werden muss..
    Grüße, Momo
    Momo ist offline Geändert von Momo (01.06.2018 um 22:53 Uhr)

  2. #2 Zitieren

    Metasyntaktische Variable
    Avatar von foobar
    Registriert seit
    Sep 2004
    Ort
    Direkt hinter dir! Buh!
    Beiträge
    24.011
    Wir haben auch ein Forum wo da heißt: "Webdesign und Programmierung"...
    foobar ist gerade online

  3. #3 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    Aah, okay danke, kann das dort hinverschoben werden bitte? ;P
    Momo ist offline

  4. #4 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.328
    Erledigt. Kannst loslegen.
    jabu ist offline

  5. #5 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    Also, ich hatte eben angefangen, einen riesigen Text mit auseinandergefriemelten Quellcodeausschnitten zu schreiben, aber dann hab ich mir mein Programm nochmal angeschaut und gefunden, wie ich mein Problem lösen kann. Es geht im Prinzip um Eltern- und Kindklassen(das sollen wir benutzen können), und wie ich bei Aufruf einer allgemeinen Elternklasse Werte aus der Kindklasse darstellen lassen kann. Es geht darum, von verschiedenen Formen/Shapes(Rechteck, Dreieck, Trapez) die Werte für Flächeninhalt und Umfang auszugeben und vor allem eine variable Anzahl an Shapes festzulegen. Demnächst soll unser Programm auch noch in der Lage sein von einem Beliebigen Shape die werte wieder ausgeben zu können, und mit den zahlenwerten hat das auch funktioniert, allerdings wollte ich eben nicht nur "Form 1 hat area= 4 und perimeter=10", "Form 2 hat...", sondern "Dreieck 1 hat ...", "Rechteck 2 hat..." und so weiter ausgeben lassen, also einen String statt einer zahl. Ich kann nachfolgend mal meinen Quelltext posten, ich markiere das was ich eben geschrieben habe und das woran ich mich orientiert habe mal farbig...
    Code:
    #include<iostream>
    #include<math.h>
    
    
    using namespace std;
    
    //Klasse Shape initialisieren --> Shape definiert die Form eines Objektes
    class Shape
    {
       protected:		//geschützte Attribute
            float perimeter;
            float area;
            string type;
            bool isCalculated;
            virtual void calculate()=0;
       public:		//öffentliche Attribute der Klasse
    
                float getPerimeter();
                float getArea();
                string getType();
                Shape();				//Constructor --> Objekt einer Klasse Shape wird erstellt
                ~Shape();				//Destructor --> Objekt einer Klasse Shape wird zerstört
    };
    
    //Konstruktor für Shape deklarieren
    Shape::Shape()
    {
       isCalculated = false;
    }
    
    //Destructor für Shape deklarieren
    Shape::~Shape()
    {
    
    }
    
    float Shape::getArea()
    {
    	if (!isCalculated)
    	 {
    		calculate();
    	 }
    	 return area;
    }
    
    float Shape::getPerimeter()
    {
    	if (!isCalculated)
    	 {
    		calculate();
    	 }
    	 return perimeter;
    }
    
    string Shape::getType()
    {
        if (!isCalculated)
        {
            calculate();
        }
        return type;
    }
    //================================================================================
    // Rectangle
    class Rectangle: public Shape
    {
       protected:
    		float base;
    		float height;
            void calculate();
       public:
            Rectangle();
            void setGeometry(float Rbase, float Rheight);
    
    };
    
    
    Rectangle::Rectangle()//konstruktor von rectangle
    {
    
    }
    
    void Rectangle::calculate() //calculate-funktion von rectangle wird definiert
    {
    		area = base * height;
    		perimeter = 2*base + 2*height;
    		isCalculated = true;
    		type = "Rectangle";
    }
    
    void Rectangle::setGeometry(float Rbase, float Rheight)
    {
    	Rectangle::base = Rbase;
    	Rectangle::height = Rheight;
    }
    
    //================================= Class rechtwinkliges Dreieck
    class rectTriangle: public Shape
    {
        protected:
            float kathete1;
            float kathete2;
            void calculate();
        public:
    
            rectTriangle();
            void setGeometry (float Kkathete1, float Kkathete2);
    };
    
    rectTriangle::rectTriangle()//Konstruktor für rectTraingle
    
    {
    
    }
    
    void rectTriangle::calculate()
    {
        area = (kathete1 * kathete2)/2;
        perimeter = (kathete1+kathete2+sqrt(kathete1*kathete1+kathete2*kathete2));
        isCalculated = true;
    }
    void rectTriangle::setGeometry (float Kkathete1, float Kkathete2)
    {
        rectTriangle::kathete1 = Kkathete1;
        rectTriangle::kathete2 = Kkathete2;
    }
    
    class Trapezoid: public Shape
    {
        protected:
            float topside;
            float botside;
            float height;
            void calculate();
        public:
            Trapezoid();
            void setGeometry(float Ttopside, float Tbotside, float Theight);
    
    };
    
    Trapezoid::Trapezoid()//Konstruktor für Trapezoid
    {
    
    }
     void Trapezoid::calculate()
     {
         area = ((topside + botside)/2)*height;
         perimeter = 0;
         isCalculated = true;
     };
    
     void Trapezoid::setGeometry(float Ttopside, float Tbotside, float Theight )
    {
        Trapezoid::topside = Ttopside;
        Trapezoid::botside = Tbotside;
        Trapezoid::height = Theight;
    }
    
    //Hauptprogramm
    int main()
    {
        bool ende = true;
        do
        {
            int number;
            cout << "How many shapes do you want?" << endl;
            cin >> number;
            Shape *Memory[number];
            int counter = 0;
            bool viableInput = true;
            do
            {
                do
                {
                cout << " What do you want to calculate?" << endl;
                cout << " 1: Rectangle(area, perimeter) \n 2: rectangular Triangle(area, triangle) \n 3: Trapezoid(area only) \n";
                int typeShape;
                cin >> typeShape;
    
                    switch (typeShape)
                    {
                        case 1:
                            {
                                cout << "Set rectangle geometry:" << endl;
                                float rectA, rectB;
                                cout << "Height: "; cin >> rectA;
                                cout << "Length: "; cin >> rectB;
                                Rectangle *Rect = new Rectangle;
                                Rect->setGeometry(rectA, rectB);
                                Memory[counter]=Rect;
                                cout << "Rectangle " <<counter+1<< " Area: " << Rect->getArea() <<endl;
                                cout << "Rectangle "<<counter+1<< " Perimeter: " << Rect->getPerimeter() <<endl;
                                counter++;
                            }
                            break;
                        case 2:
                            {
                                cout << "Set rectangular triangle geometry:" << endl;
                                float triA, triB;
                                cout << "Kathete 1: "; cin >> triA;
                                cout << "Kathete 2: "; cin >> triB;
                                rectTriangle *rT = new rectTriangle;
                                rT->setGeometry(triA, triB);
                                Memory[counter]=rT;
                                cout << "Rectangle" <<counter+1<< " Area: " << rT->getArea() <<endl;
                                cout << "Rectangle "<<counter+1<<" Perimeter: " << rT->getPerimeter() <<endl;
                                counter++;
                            }
                            break;
                        case 3:
                            {
                                cout << "Set Trapezoid geometry:" <<endl;
                                float trapA, trapB, trapC;
                                cout << "Top side: "; cin >> trapA;
                                cout << "Bottom side: "; cin >> trapB;
                                cout << "Height: "; cin >> trapC;
                                Trapezoid *Trap =new Trapezoid;
                                Trap->setGeometry(trapA, trapB, trapC);
                                Memory[counter]=Trap;
                                Trap->setGeometry(trapA, trapB, trapC);
                                cout << "Trapeziod area: " << Trap->getArea() << endl;
                                cout << "Trapezoid perimeter not definable" <<endl;
                                counter++;
                            }
                            break;
                        default:
                            viableInput=false;
                            cout << "Please choose a given Shape! \n" ;
                            break;
                    }
                }
                while (counter<number);
    
            }
            while(!viableInput);
    
        cout << "What do you want to do now? \n 1: do it again \n 2: display values again \n anything else: close" <<endl;
        int shut;
        cin >> shut;
        switch(shut)
            {
                case 1:
                    {
                        ende= false;
                    }
                    break;
                case 2:
                    {
                        int typeOut;
                        cout << "Which shapes informations do you want to have displayed again?" << endl;
                        cout << " 1: all \n 2: individual ones " << endl;
                        cin >> typeOut;
                        bool outrepeat=true;
                        do
                        {
                            switch(typeOut)
                            {
                                case 1:
                                    {
                                        int i=0;
                                        do
                                        {
                                            cout << Memory[i]->getType() << " "<< i+1 <<" area: "<< Memory[i]->getArea()<<", perimeter: " <<          Memory[i]->getPerimeter()<<endl;
                                            i++;
                                        }
                                        while (i<number);
                                    }
                                break;
                                case 2:
                                    {
    
                                    }
                                break;
                                default:
                                    {
                                    cout << "Please choose an option!" <<endl;
                                    outrepeat=false;
                                    }
                                break;
                            }
                        }
                        while(!outrepeat);
    
                    }
                default:
                    {
                        return 0;
                    }
                    break;
            }
        }
        while(!ende);
    
        return 0;
    }
    also es funktioniert jetzt, ich dachte am anfang, dass ich es irgendwie schaffen muss sowas wie einen "virtual string" einzufügen, wie ich dieses "virtual void calculate()" benutzt habe.. aber dann ist mir aufgefgallen, dass void ja gar nichts zurückgibt, sondern in Shape die werte von area und perimeter ändert, und dass ich das selbe im gleichen zuge ja auch mit einer string variable machen kann.. also das problem ist jetzt zumindest schonmal gelöst, fehlt halt noch code für die anderen fälle ;P wer will kann das programm ja mal ausprobieren zur besseren verständlichkeit, es funktioniert aber so wie ich es mir vorstelle grade nur mit "Rectangle" als Form.

    aber da wir jede woche mehr mit dem programm machen sollen, wird das nicht die letzte frage gewesen sein, der nächste schritt ist dann irgendwie, das feld Memory[] dynamisch anlegen zu lassen falls man das so bezeichnet.. und da stehe ich momentan noch komplett auf dem schlauch.
    Momo ist offline Geändert von Momo (01.06.2018 um 22:23 Uhr)

  6. #6 Zitieren
    Tieftöner Avatar von Lookbehind
    Registriert seit
    Dec 2007
    Beiträge
    15.176
    Klassischer Fall von Rubberduck-Debug

    Um es eleganter zu machen, könntest du das Setzen des Type übrigens auch in den Constructor auslagern, oder gleich in der erbenden Klasse fest überschreiben, da sich der Shape-Type ja über die Zeit nicht ändert. Aber das führt vielleicht ein wenig an der eigentlichen Lektion vorbei. Da gehts ja manchmal nicht darum etwas möglichst elegant zu erschlagen, sondern euch ein Konzept bei zu bringen.

    Wo wir gerade bei dem Thema sind ...
    Zitat Zitat von Momo Beitrag anzeigen
    ...
    aber da wir jede woche mehr mit dem programm machen sollen, wird das nicht die letzte frage gewesen sein, der nächste schritt ist dann irgendwie, das feld Memory[] dynamisch anlegen zu lassen falls man das so bezeichnet.. und da stehe ich momentan noch komplett auf dem schlauch.
    Ich rieche malloc um die Ecke kommen. Falls dem so sein sollte: Gewöhn dir bitte von Anfang an an, den Speicher auch sauber wieder frei zu geben. Ich weiß, du wirst wahrscheinlich später nicht als Software-Entwickler arbeiten. Aber du wirst evtl mit ihnen zu tun haben und auch mal deren Code vor die Nase bekommen. Du solltest in der Lage sein, zu erkennen, wann das nicht gemacht wurde und dem Programmierer dann auf die Finger zu klopfen. Das ist nämlich leider ein immer noch sehr gängiger Fehler, auch unter Profis. Und der macht dann Jahre später echt fiese Sicherheitslücken!
    (Oder man vermeidet malloc am besten gleich ganz, aber da seid ihr vermutlich noch nicht.)
    Lookbehind ist offline

  7. #7 Zitieren
    Ritter
    Registriert seit
    Feb 2003
    Beiträge
    1.554
    Ich bin zwar kein Experte in C++. Ich habe mit C++ auch nicht so viel am Hut gehabt, da ich beruflich mit C# arbeite aber ein paar Tipps zu deinem Code:
    Halte das KISS-Prinzip ein (Keep it simple and stupid)

    Das wird dir das Leben erleichtern und würde auch die Klassen schlanker und lesbarer halten.

    Was mir schon mal auffält, ist, dass du dein Code mit einer vermeintlichen Mikrooptimierung zumüllst. Und zwar die unnötige Calculate()-Methode, die den Code unlesbar und zudem noch zu viel macht und auch eine große Fehlerquelle ist. Lass doch den Flächeninhalt und den Umfang in den dafür vorgesehenden Methoden ausrechnen. Es macht den Code deutlich einfacher, verständlicher und lesbarer. Stell dir vor, du würdest von jemanden deine Shape-Klasse bekommen und du sollst dafür jetzt Ableitungen schreiben. Würdest du ohne Dokumentation verstehen, wie du die Ableitungen schreiben sollst? Du siehst ein isCalculated-Flag, eine Calculate()-Methode und getArea() und getPerimeter(). Ohne eine Dokumentation wüsste ich nicht, wozu ich nun isCalculated und Calculate() benötige. Wenn du nun Shape aber auf das wesentliche reduzierst, also:
    Code:
    class Shape {
       public:
          virtual float getArea() = 0;
          virtual float getPerimeter() = 0;
          virtual string getType() = 0;
    };
    Ist nun verständlich, was die Klasse tun soll. Gut, getType() bräuchte vielleicht eine Erklärung aber es ist hier klar, dass Ableitungen den Flächeninhalt und den Umfang berechen müssen. Das Problem mit deiner Calculate() ist auch, dass Änderungen von deiner Shape-Klasse nicht sichtbar werden. Angenommen, du willst noch eine dritte Berechnung vornehmen und erweiterst dafür Shape. Die Berechnung findet weiterhin in Calculate() statt. Der Code ist aber weiterhin kompilierbar, da alle abgeleiteten Klassen ja Calculate() besitzen aber die neue Berechnung würde bei den Ableitungen 0 ergeben, da sie die neue Berechnung nicht berechnen. Viel besser wäre es, wenn man vom Compiler eine Fehlermeldung bekommt, wenn bei den Ableitungen die neue Berechnung fehlt. Wir nutzen also den Compiler, um solche Fälle zu finden. In deinem Code mag es vielleicht noch leicht sein aber stell dir nun mal ein Code mit Tausend Klassen und Millionen von Codezeilen vor. Dann wird es mit einfachen Mitteln nicht mehr so einfach sein, alle Stellen im Code zu finden.

    Das nächste, was mir auffällt, ist die setGeometry()-Methode in den Ableitungen. Die Methode ist kein Bestandteil von Shape, sondern von den konkreten Ableitungen. Also sowas wie
    Code:
    Shape *rect = new Rectangle;
    rect->setGeometry(...);
    könntest du nicht schreiben, weil Shape die setGeometry()-Methode nicht kennt. Ein weiteres Problem mit setGeometry() taucht jetzt nun auch mit einer o.g. Mikrooptimierung auf, denn du musst nun zwigend als erstes setGeometry() aufrufen, bevor du getArea(), getPerimeter() oder getType() aufrufst, denn ansonsten sind die Ergebnisse immer 0. Ein weiterer aufruf von setGeometry() ist dann nicht mehr möglich bzw. ist schon möglich aber dein Obekt befindet sich dann in einem korrupten Zustand, da die Geometriedaten nicht mehr mit den berechneten Ergebnissen übereinstimmen.

    Für diese Fälle gibt es ja den Konstruktor. Reiche doch die erforderlichen Daten über den Konstruktor rein und alles ist gut.

    Eine Implementierung für ein Rechteck sieht dann so aus:
    Code:
    class Rectangle: public Shape {
        private:
            float width, height;
    
        public:
          Rectangle(float width, float height) { 
                width = width; 
                height = height; 
          }
    
          float getArea() { 
             return width * height; 
          }
          
          float getPerimeter() {
            return 2 * width + 2 * height;
          }
       
          string getType() {
            return "Rechteck";
          } 
    };
    Ganz simpel. Ohne viel Schnick-Schnack. Ableitungen lassen sich ganz leicht schreiben und Anpassungen an Shape würden sofort einen Kompilierfehler in den Ableitungen quittiert werden. Ein weiterer Vorteil ist nun, dass die Berechnungsformel nun direkt in den Methoden stehen und nicht in Calculate(). Das macht den Code lesbarer, da man nun weiß, wo man im Code suchen muss, um zu wissen, was berechnet wird. Ansonsten müsste man wissen, dass die Berechnung in Calculate() stattfindet und stattfinden muss.

    Du hast also mit viel Code viele Fehlerquellen eingebaut. Darum "Keep it simple and stupid".
    (ich hoffe, das ist valider C++ Code ^^")
    Whiz-zarD ist offline Geändert von Whiz-zarD (03.06.2018 um 12:01 Uhr)

  8. #8 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    Das war jetzt schon ganz schön viel auf einmal (für mich)..
    Also ich werd mal versuchen mich dessen anzunehmen, danke auf jeden Fall dass ihr es mal durchgegangen seid!
    Ich hab halt echt das Problem, dass wir teilweise irgendwas benutzen weil es sich empfiehlt und wir selber keine Alternativen bringen können und dann nicht so wirklich wissen was bestimmte Teile so konkret machen oder auch machen könnten..
    Naja, ich werd mich nicht das letzte Mal gemeldet haben diesbezüglich :confused :
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline

  9. #9 Zitieren
    Ritter
    Registriert seit
    Feb 2003
    Beiträge
    1.554
    Zitat Zitat von Momo Beitrag anzeigen
    Ich hab halt echt das Problem, dass wir teilweise irgendwas benutzen weil es sich empfiehlt und wir selber keine Alternativen bringen können und dann nicht so wirklich wissen was bestimmte Teile so konkret machen oder auch machen könnten..
    Was genau meinst du mit diesem Satz?
    Whiz-zarD ist offline

  10. #10 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    naja wenn der dozent dir nen denkanstoß gibt dann ist das idealerweise ja nicht die endgültige lösung.. aber da wir eben außer dem was er uns vorschlägt zu benutzen an codestückchen ja keine ahnung so richtig haben können wir nicht so wirklich altrnativen bringen, auch wenn es diese praktisch gäbe und sie vielleicht viel sinnvoller wären.
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline

  11. #11 Zitieren
    Ritter
    Registriert seit
    Feb 2003
    Beiträge
    1.554
    Ich denke dann mal, dass die Idee von isCalculated und Calculate() vom Dozenten stammt. Dozenten haben oft keine Berufserfahrung als Softwareentwickler und oft ist auch ihr Wissen veraltet und bezieht sich nur auf kleine Beispiele. Das Konstrukt von isCalculated und Calculate() ist zwar schön und gut aber so sollte man heutzutage keine Software mehr entwickeln. Dieses Konstrukt soll ein Cache darstellen, damit die Berechnung nur ein mal stattfindet und die Ergebnisse dann gecached werden aber who cares? Dann wird eben halt der Wert ständig neu berechnet. Bei solchen Berechnungen tut das auch nicht weh. Ein Cache würde ich erst implementieren, wenn ich merke, dass es Performanceprobleme gibt. Bis dahin versuche ich den Code sauber und lesbar zu halten.

    2005 veröffentlichten Robert C. Martin, Bertrand Meyer und Barbara Liskov die sog. SOLID-Prinzipien. Prinzipien, wie ein objektorientierter Code aufgebaut sein sollte. SOLID steht für:
    Single-Responsibility-Prinzip
    Open-Closed-Prinzip
    Liskovsches Substitutionsprinzip
    Interface-Segregation-Prinzip
    Dependency-Inversion-Prinzip

    Das Single-Responsibility-Prinzip besagt, dass eine Klasse und/oder eine Methode nur eine Sache machen soll.
    Wenn man sich aber mal dein Beispiel anschaut, so ich die Shape-Klasse nicht nur die Basisklasse für Geometrische Figuren, sondern sie stellt auch ein Caching bereit. Die Calculate()-Methode macht gleich drei Dinge auf einmal. Sie berechnet den Umfang, den Flächeninhalt und initialisiert den Typnamen.

    Wenn man ein Cache benötigt, dann würde ich eine weitere Klasse bauen, die die Werte speichert. Somit bleibt Shape und deren Ableitungen frei vom Cache und bleiben sauber.
    Whiz-zarD ist offline

  12. #12 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    okay also kurz zur situation mit dem dozenten: der typ ist der absolute G.
    der hat jahrelang in hackergruppen gearbeitet, betreut mehrere robotikprojekte und fliegt laufend zu veranstaltungen wo er irgendwelche auszeichnungen mit seinen teams kriegt, demnächst in Las Vegas. ABER: er wurde eine woche vor semesterbeginn ersatzweise als dozent für uns herangezogen in dem glauben dass wir seit 3 semestern informatik studieren. als er dann nach 10 minuten langsam stutzig wurde, dass wir absolut keine ahnung haben hat ihm gedämmert, dass da keine informatiker sitzen, sondern in unserem fall dann maschinenbauer. dann musste er von jetzt auf gleich irgendwie ein crashkurs-programm für leute die C und C++ noch nicht kennen aufziehen. das mit der calculate-methode war zwar seine idee, aber wie wir das genau machen ist ihm wirklich egal, eigentlich würde er es wie gesagt gerne sehen, wenn wir selber einen anderen ansatz finden. große teile des programms haben wir dann irgendwie in der gruppe angeglichen, weil einer ne idee hatte die wir dann alle übernommen haben, weil sie das machte was wir grade irgendwie dachten zu brauchen, das mit dem setGeometry zum beispiel. aber da es funktioniert hat und das gemacht hat was wir wollten und der auch dauernd was neues von uns wollte haben wir es eben alle übernommen, um lieber die neuen aufgaben anzugehen. darum ist der code für auskenner wohl echt abstrus. also alles in allem ist der dozent komplett überqualifiziert für das was wir machen sollen und er kann auch überhaupt nicht einschätzen wie viel er uns zutrauen kann, und das kann genauso schlecht sein wie wenn der dozent zu wenig ahnung hat(was ich ehrlichgesagt noch nicht erlebt habe)
    also ich meine, ich kann zumindest erklären was die abschnitte in dem programm machen, aber ich kann die einzelnen elemente größtenteils nicht fachsprachlich benennen, und mir fehlt eben das wissen, wie man die funktionen von den elementen die man da einbauen kann sinnvoll nutzt und ausschöpft.. klar, ich könnte natürlich einen online-programmierkurs mir suchen oder ein buch, nur dann mach ich eben nur noch das die ganze woche wenn ich da dann durchblick haben will.. wir haben eben auch nicht nur OOP, sondern auch normal informatik, nur der dozent dort ist eben auch der der das immer macht und schon seit jahren unterrichtet, und bei ihm programmieren wir imperativ, was ja ein komplett anderer ansatz ist. das heißt, der dozent erklärt da natürlich auch was denn jedes einzelne konstrukt was wir dann benutzen macht und wie es funktioniert, aber die beispiele in den seminaren sind dann eben auch so, dass nicht gleich von anfang an alles auf einmal auf einen einprasselt, sondern dass man das übt was wir in der vorlesung behandelt haben und die bereits behandelten elemente progressiv mit einbezogen werden, aber nichts benutzt wird wovon wir noch keine ahnung haben. war jetzt ein langer text, aber vielleicht hilft es den verbockten quelltext zu erklären..

    morgen oder das mal danach will er ne theoriearbeit schreiben und danach unser aktuelles programm erklärt haben.. ersteres wird übel, weil ich nicht mal weiß was ich lernen soll..
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline Geändert von Momo (03.06.2018 um 23:11 Uhr)

  13. #13 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    habe jetzt zumindest die klassen neu geschrieben, ich poste mal den code hier :P

    Code:
    #include<iostream>
    #include<math.h>
    
    
    using namespace std;
    //Elternklasse
    class Shape {
        protected:
            float area;
            float perimeter;
            string type;
        public:
            virtual void getArea()=0;
            virtual void getPerimeter()=0;
            Shape();
            ~Shape();
    };
    Shape::Shape()
    {
    
    }
    Shape::~Shape()
    {
    
    }
    //========================================================================================================================
    //Kindsklasse rectangle
    class Rectangle: public Shape{
        protected:
            float height;
            float width;
        public:
            //Konstruktor für Rectangle setzt höhe und breite mit den eingabewerten gleich und den type auf rectangle(für die ausgabe)
            Rectangle(float Rheight, float Rwidth){
            height=Rheight;
            width=Rwidth;
            type="rectangle";
            }
    
            void getArea(){
            area=(width*height);
            }
    
            void getPerimeter(){
            perimeter=(2*width)+(2+height);
            }
    };
    //=========================================================================================================================
    //KIndsklasse rectangular triangle
    class rectTriangle: public Shape{
        protected:
            float kathete1;
            float kathete2;
        public:
            //Konstruktor für Triangle setzt die kathetenwerte mit den eingabewerten gleich und den type auf rectangular triangle
            rectTriangle(float Tkathete1, float Tkathete2){
            kathete1=Tkathete1;
            kathete2=Tkathete2;
            type="rectangular triangle";
            }
    
            void getArea(){
            area=((kathete1*kathete2)/2);
            }
    
            void getPerimeter(){
            perimeter=(kathete1+kathete2+sqrt(kathete1*kathete1+kathete2*kathete2));
            }
    };
    //=========================================================================================================================
    //Kindsklasse Circle
    class circle: public Shape{
        protected:
            float diameter;
        public:
            //Konstruktor für Circle setzt diameterwert mit eingabewert gleich und setzt type auf circle
            circle(float Cdiameter){
            diameter=Cdiameter;
            type="Circle";
            }
    
            void getArea(){
            area=((M_PI)/4)*diameter*diameter;
            }
    
            void getPerimeter(){
            perimeter=(M_PI)*diameter;
            }
    
    };
    //==========================================================================================================================
    int main()
    {
        return 0;
    }
    int main() wird jetzt nochmal lustig, aber dank eurer tips ist die klassendefinition schonmal viel übersichtlicher!
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline

  14. #14 Zitieren

    Metasyntaktische Variable
    Avatar von foobar
    Registriert seit
    Sep 2004
    Ort
    Direkt hinter dir! Buh!
    Beiträge
    24.011
    Die privaten Variablen für area und perimeter kannst du eigentlich aus Shape rauswerfen. Die werden ja jetzt gar nicht mehr gebraucht.

    Was mich noch interessieren würde: Brauchen deine geometrischen Formen keine Position? Das hängt halt von der Aufgabenstellung ab, aber normalerweise definiert sich ein Rechteck nicht nur durch Breite und Höhe. Sondern man braucht auch einen Koordinatenpunkt, an dem man es festmachen will. Nur dann kann man es bspw. auch verschieben, zeichnen, auf Überdeckung prüfen und so weiter...
    foobar ist gerade online

  15. #15 Zitieren
    Ritter
    Registriert seit
    Feb 2003
    Beiträge
    1.554
    Zitat Zitat von foobar Beitrag anzeigen
    Was mich noch interessieren würde: Brauchen deine geometrischen Formen keine Position?
    Es geht doch nur darum, einen Rechner zu bauen, der den Flächeninhalt und Umfang berechnet. Es soll ja nichts gezeichnet werden. Wozu dann Koordinaten?
    Whiz-zarD ist offline

  16. #16 Zitieren

    Metasyntaktische Variable
    Avatar von foobar
    Registriert seit
    Sep 2004
    Ort
    Direkt hinter dir! Buh!
    Beiträge
    24.011
    Zitat Zitat von Whiz-zarD Beitrag anzeigen
    Es geht doch nur darum, einen Rechner zu bauen, der den Flächeninhalt und Umfang berechnet. Es soll ja nichts gezeichnet werden. Wozu dann Koordinaten?
    Wenn das wirklich alles ist, dann braucht man es wirklich nicht. Daher auch mein Hinweis, dass es von der konkreten Aufgabenstellung abhängt. Aber allgemein lieber nochmal der Hinweis. Nicht, dass der OP sich einfach so sehr auf den Berechnungskram und die Vererbung konzentriert, dass er das andere vergisst. Den Wald vor lauter Bäumen nicht zu sehen passiert jedem mal.
    foobar ist gerade online

  17. #17 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    nee, keine sorge, das ist wirklich dann alles was damit gemacht werden soll! ich würde area und perimeter gerne als richtige werte behalten, nicht nur die funktionen getarea() und getperimeter() die einen rückgabewert haben...
    gab es ansonsten noch verbesserungsvorschläge?
    das nächste was wir machen sollen ist, einen "container" zu bauen in den beliebig viele objekte der klasse shape fortlaufend hineingeschrieben werden können und die daten später wieder rausgeholt werden können. dann soll von allen shapes area und perimeter aufaddiert werden, aber da versuch ich mich erstmal selber dran.
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline Geändert von Momo (04.06.2018 um 16:46 Uhr)

  18. #18 Zitieren

    Metasyntaktische Variable
    Avatar von foobar
    Registriert seit
    Sep 2004
    Ort
    Direkt hinter dir! Buh!
    Beiträge
    24.011
    Zitat Zitat von Momo Beitrag anzeigen
    nee, keine sorge, das ist wirklich dann alles was damit gemacht werden soll! ich würde area und perimeter gerne als richtige werte behalten, nicht nur die funktionen getarea() und getperimeter() die einen rückgabewert haben...
    Ich verstehe den Sinn ehrlich gesagt nicht so richtig. Ich bin auch nicht so fit in Sachen C++, also vielleicht verstehe ich hier was falsch. Aber beim Rechteck hast du z.B. stehen:

    Code:
    void getArea() {
            area=(width*height);
    }
    Das heißt, die Funktion berechnet die Fläche und speichert sie im Feld area. Dann beendet sie sich, ohne einen Wert zurück zu geben. Sie ist ja vom Typ "void". Der Aufrufer müsste jetzt irgendwie das Feld area auslesen. Aber da kommt er i.d.R. nicht ran, weil es geschützt ist. So, wie der Code da steht, kann ich z.B. nicht "x = myshape->getArea()" aufrufen, um an die Fläche zu kommen.

    Eigentlich ist die Idee doch, das Feld hinter der Methode zu kapseln, oder nicht?

    Also so:
    Code:
    float getArea() {
            area=(width*height);
            return area;
    }
    Und da ist area eigentlich hyperfluid und du kannst die Fläche direkt zurückgeben. Der Compiler wird das vermutlich eh rausoptimieren (eine Variable, die nie ausgelesen wird, braucht halt keiner, also kann die auch weg).

    Ansonsten, wenn area auch einen Sinn haben soll (als Cache für den Wert), dann musst du doch wieder zur calculate()-Methode greifen. Und dann in setGeometry() und jeder anderen Methode, die die Maße der Form verändert, das isCalculated-Flag wieder auf false setzen. Damit das Objekt weiß, dass es neu berechnen muss.
    foobar ist gerade online Geändert von foobar (04.06.2018 um 17:04 Uhr)

  19. #19 Zitieren
    Pretty Pink Pony Princess  Avatar von Multithread
    Registriert seit
    Jun 2010
    Ort
    Crystal Empire
    Beiträge
    11.228
    Zitat Zitat von foobar Beitrag anzeigen
    Und da ist area eigentlich hyperfluid und du kannst die Fläche direkt zurückgeben. Der Compiler wird das vermutlich eh rausoptimieren (eine Variable, die nie ausgelesen wird, braucht halt keiner, also kann die auch weg).

    Ansonsten, wenn area auch einen Sinn haben soll (als Cache für den Wert), dann musst du doch wieder zur calculate()-Methode greifen. Und dann in setGeometry() und jeder anderen Methode, die die Maße der Form verändert, das isCalculated-Flag wieder auf false setzen. Damit das Objekt weiß, dass es neu berechnen muss.
    Ich würde dann mit einem Lazy Load arbeiten und einer Clear Methode.
    Code:
    public class Rechteck{
      private int? area;
      public int getArea()
      {
        if(area==null){
          area=width*length);
        }
        return area;
      }
    
      public void CLear(){
        area=null;
      }
    
      public void setSize(int inlenght, int inWidth){
        //Felder setzen
    
        Clear();
      }
    }
    Dadurch kannst du beim neu schreiben einer der Angaben 'Clear' aufrufen und beim nächsten mal abfragen von getArea() stimmt die Fläche.

    PS: der Code dürfte so noch nicht ganz gehen, Ich bin mir nicht ganz sicher bezüglich der C++ Syntax.
    Im C#, würde man Area und Perimeter als Properties lösen, ggf. mit dem von ir oben beschriebenen Lazy Load.
    [Bild: AMD_Threadripper.png] Bei Hardware gibt es keine eigene Meinung, bei Hardware zählen nur die Fakten.


    Probleme mit der Haarpracht? Starres Haar ohne Glanz? TressFX schafft Abhilfe. Ja, TressFX verhilft auch Ihnen zu schönem und Geschmeidigen Haar.
    [Bild: i6tfHoa3ooSEraFH63.png]
    Multithread ist offline

  20. #20 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.328
    Zitat Zitat von Multithread Beitrag anzeigen
    Ich würde dann mit einem Lazy Load arbeiten und einer Clear Methode.
    [...]
    PS: der Code dürfte so noch nicht ganz gehen, Ich bin mir nicht ganz sicher bezüglich der C++ Syntax.
    Im C#, würde man Area und Perimeter als Properties lösen, ggf. mit dem von ir oben beschriebenen Lazy Load.
    Funktioniert leider nicht, denn bei C++ sind die Typen nicht nullable. Vielleicht schaffe ich es heute abend noch, etwas zu posten.
    jabu ist offline

Seite 1 von 2 12 Letzte »

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •