a.exe funktioniert nicht mehr



  • Markus97 schrieb:

    Auch wenn der Trick mit sizeof nicht funktioniert und ich es stattdessen mit einer 2 austausche, stürzt das Programm leider ab.

    Geht aber schon in die richtige Richtung.

    ein Figur*[3] hat übrigens auch nur 3 Elemente (0,1 und 2).
    Und was soll der cast noch? Du weisst doch, dass das Array Figur* enthält.

    Figur ist übrigens das Paradebeispiel für eine abstrakte (Basis-)Klasse. Wäre es nicht sinnvoll, wenn man keine Instanzen von Figur erstellen kann? Z.b. weil man eh nix damit machen kann?
    Zeichnen? Was?
    Flaeche berechnen? Wie?



  • Ja, genau das müssen sie. In anderen Sprachen muss das nicht unbedingt so sein, aber da ist das auch hinter Abstraktion versteckt. z.B. unterstützt Java eben diese Co- bzw. Kontravarianzen.

    Zu deinem Programm:
    Wenn du das wirklich so geshcrieben hast, ohne Funktiosnaufruf zwischen den Figuren und der Schleife (sprich ohne, dass das Array zu einem pointer degeneriert) sollte das eigentlich klappen. Aber es geht auch besser.

    Dann dein dynamic_cast ist immer noch unnötig, denn dein "Objekt" ist eine Figur (oder Unterklasse, aber damit ists auf jedenfall eine Figur!), du musst nicht nochmal eine Figur draus machen.
    Der Nullcheck kann bleiben, aber prüf da gegen nullptr und nicht gegen 0.

    Das hier wäre ein Vorschlag wie das ganze etwas eifnacher gehen würde.

    std::vector<std::unique_ptr<Figure>> fig;
    //std::array<std::unique_ptr<Figure>, 4> fig; // egal ob std::vector doer std::array
    
    fig.push_back(std::make_unique<Figure>(0, -1));
    fig.push_back(std::make_unique<Kreis>(0,0,1));
    fig.push_back(std::make_unique<Rechteck>(0,1,2,2));
    fig.push_back(std::make_unique<Quadrat>(0,2,3));
    
    // Gebe die Figuren auf der Konsole aus.
    for(auto const& f : fig)
    	std::cout << f->asString() << std::endl;
    
    for(unsigned int i = 0; i < fig.size()-1; i++)
    {
    	double f1 = (fig[i] == nullptr) ? 0 : fig[i]->berechneFlaeche();
    	double f2 = (fig[i+1] == nullptr) ? 0 : fig[i+1]->berechneFlaeche();
    
    	if (f2>f1)
    		index++;
    }
    


  • ein Figur*[3] hat übrigens auch nur 3 Elemente (0,1 und 2).

    Stimmt, das habe ich übersehen. Leider stürzt die exe-Datei wieder ab.

    Figur ist übrigens das Paradebeispiel für eine abstrakte (Basis-)Klasse. Wäre es nicht sinnvoll, wenn man keine Instanzen von Figur erstellen kann? Z.b. weil man eh nix damit machen kann?
    Zeichnen? Was?
    Flaeche berechnen? Wie?

    Den Sinn dieser komischen Aufgabe hinterfrage ich erst garnicht 😃
    Laut Aufgabenstellung sollte ich es so programmieren.



  • Skym0sh0 danke für die Mühe. Ich würde es auch gerne mit Vektoren lösen, jedoch muss ich laut Aufgabenstellung ein Array verwenden.

    Eine 0 habe ich aus dem Grund verwendet, weil ich bei Nullpointern die Fehlermeldung "nullptr was not declared in this scope" erhalte.



  • Okay, was hast du für einen Compiler?
    Im (halbwegs) aktuellen MSVC ist nullptr drin und bei nem GCC Derivat musstes mit -std=c++11(oder so ähnlich) aktivieren.

    Hast du einen Debugger zur Hand? Wenn ja nutz ihn, dann siehst du wo es kracht (bzw solltest sehen).

    Und zeig mal am besten den gesamten Quellcode, wenn er denn die paar hundert Zeilen nicht übersteigt.



  • Wie gesagt, es gibt auch std::array, und wenn das dir verboten wird, dann würde ich aber mal nach einem guten Grund fragen, denn es ist im Prinzip ein C-Style Array, aber besser (Es gibt glaub manche die meinen, das C-Style Array wäre schneller, mag sein, weiß nicht, aber das ist in diesem Fall wohl nicht von Bedeutung).

    Übrigens, für nullptr musst du glaub C++11 "aktivieren". (googeln)

    @Skym0sh0:
    "array-to-pointer-decay" Danke, genau so ein Begriff hat mir gefehlt 😃
    Ich wollte in meinem Beispiel auch eigentlich verdeutlichen, dass man da das "a" verwenden soll, also die eigentliche Größe, um eben solchen Problemen zuvorzukommen.

    Ich will noch anmerken, dass solche "asString" "toString" methoden auch nicht gerade C++-like sind. Wozu kann man den << Operator überladen.
    Und wirklich komplizierter ist das auch nicht, wenn man schon so eine toString Funktion hat.



  • Ich kompiliere die Codes mit dem Befehl g++ -Wall .cpp.
    Als Kompilierer verwende ich mingGW.
    Hier der Code für die Basisklasse:
    cpp:

    #include "figur.hpp"
    
    Figur::Figur(double pos_x, double pos_y)
      : pos_x(pos_x), pos_y(pos_y){}
    
    Figur::~Figur(){}
    
    void Figur::verschiebe(double dx, double dy)
    {
      pos_x += dx;
      pos_y += dy;
    }
    
    std::string Figur::asString()
    {
      return "Dies ist eine Figur. Koordinaten: ("
        + std::to_string(pos_x) + "," + std::to_string(pos_y) + ")";
    }
    

    hpp:

    #ifndef FIGUR_HPP
    #define FIGUR_HPP
    
    #include <string>
    #include "tostring.hpp"
    
    class Figur
    {
    protected:
      // Attribute
      double pos_x;
      double pos_y;
    
    public:
      // Konstruktor
      Figur(double pos_x, double pos_y);
      //Destruktor
      virtual ~Figur();
      // Verschiebt die Figur um dx in x-Richtung und um dy in y-Richtung.
      void verschiebe(double dx, double dy);
      // Gibt einen den die Figur beschreibenden String zurueck.
      virtual std::string asString();
    };
    
    #endif
    

    main-Datei:

    #include <iostream>
    
    /* Das Einbinden der Header-Dateien wuerde 
     * ohne Include-Guards zum mehrfachen Einbinden
     * der selben Header-Datei (z.B. figur.hpp) fuehren. 
     */
    #include "figur.hpp"
    #include "kreis.hpp"
    #include "rechteck.hpp"
    #include "quadrat.hpp"
    
    int main()
    {
    
    	//Erzeugung des Arrays mit den jeweiligen Figuren
    	Figur* fig[4];
    	fig[0]=new Figur(0,-1);
    	fig[1]=new Kreis(0,0,1);
    	fig[2]=new Rechteck(0,1,2,2);
    	fig[3]=new Quadrat(0,2,3);
    
        // Gebe die Figuren auf der Konsole aus.
        std::cout << fig[0]->asString() << std::endl;
        std::cout << fig[1]->asString() << std::endl;
        std::cout << fig[2]->asString() << std::endl;
        std::cout << fig[3]->asString() << std::endl;
    
    	int index=0;
    	for(unsigned int i=0;i<2;i++){
    		//Berechnung der Fläche beim aktuellen Index
    		double f1;
    		Kreis* k1= dynamic_cast<Kreis*>(fig[i]);
    		Quadrat* q1=dynamic_cast<Quadrat*>(fig[i]);
    		Rechteck* r1=dynamic_cast<Rechteck*>(fig[i]);
    		if (q1!=0){f1=q1->berechneFlaeche();}
    		if (r1!=0){f1=r1->berechneFlaeche();}
    		if (k1!=0){f1=k1->berechneFlaeche();}
    		else{f1=0;}
    		double f2;
    		Kreis* k2= dynamic_cast<Kreis*>(fig[i+1]);
    		Quadrat* q2=dynamic_cast<Quadrat*>(fig[i+1]);
    		Rechteck* r2=dynamic_cast<Rechteck*>(fig[i+1]);
    		if (q2!=0){f2=q1->berechneFlaeche();}
    		if (r2!=0){f2=r1->berechneFlaeche();}
    		if (k2!=0){f2=k1->berechneFlaeche();}
    		else{f2=0;}
    		if (f2>f1){index++;}
    
    		}
        // Verschiebe Figuren
        fig[0]->verschiebe(10,10);
        fig[1]->verschiebe(10,10);
        fig[2]->verschiebe(10,10);
        fig[3]->verschiebe(10,10);
    
        // Gebe die Figuren auf der Konsole aus
        std::cout << fig[0]->asString() << std::endl;
        std::cout << fig[1]->asString() << std::endl;
        std::cout << fig[2]->asString() << std::endl;
        std::cout << fig[3]->asString() << std::endl;
    
        // Bereinige Speicher.
        delete fig[0];
        delete fig[1];
        delete fig[2];
        delete fig[3];
    
    }
    


  • Klassischer copy/paste-Fehler:

    if (q1!=0){f1=q1->berechneFlaeche();}
    if (r1!=0){f1=r1->berechneFlaeche();}
    if (k1!=0){f1=k1->berechneFlaeche();}
    else{f1=0;}
    double f2;
    Kreis* k2= dynamic_cast<Kreis*>(fig[i+1]);
    Quadrat* q2=dynamic_cast<Quadrat*>(fig[i+1]);
    Rechteck* r2=dynamic_cast<Rechteck*>(fig[i+1]);
    if (q2!=0){f2=q1->berechneFlaeche();}
    if (r2!=0){f2=r1->berechneFlaeche();}
    if (k2!=0){f2=k1->berechneFlaeche();}
    //     hier: --^
    


  • In der Zukunft sollte ich lieber konzentrierter den Code durchgehen bevor ich hier um Hilfe bitte 🙄 🙄 🙄
    Danke für die Fehlersuche 👍



  • Markus97 schrieb:

    main-Datei:

    #include <iostream>
    
    /* Das Einbinden der Header-Dateien wuerde 
     * ohne Include-Guards zum mehrfachen Einbinden
     * der selben Header-Datei (z.B. figur.hpp) fuehren. 
     */
    #include "figur.hpp"
    #include "kreis.hpp"
    #include "rechteck.hpp"
    #include "quadrat.hpp"
    
    int main()
    {
      
    	//Erzeugung des Arrays mit den jeweiligen Figuren
    	Figur* fig[4];
    	fig[0]=new Figur(0,-1);
    	fig[1]=new Kreis(0,0,1);
    	fig[2]=new Rechteck(0,1,2,2);
    	fig[3]=new Quadrat(0,2,3);
    
        // Gebe die Figuren auf der Konsole aus.
        std::cout << fig[0]->asString() << std::endl;
        std::cout << fig[1]->asString() << std::endl;
        std::cout << fig[2]->asString() << std::endl;
        std::cout << fig[3]->asString() << std::endl;
    	
    	
    	
    	int index=0;
    	for(unsigned int i=0;i<2;i++){
    		//Berechnung der Fläche beim aktuellen Index
    		double f1;
    		Kreis* k1= dynamic_cast<Kreis*>(fig[i]);
    		Quadrat* q1=dynamic_cast<Quadrat*>(fig[i]);
    		Rechteck* r1=dynamic_cast<Rechteck*>(fig[i]);
    		if (q1!=0){f1=q1->berechneFlaeche();}
    		if (r1!=0){f1=r1->berechneFlaeche();}
    		if (k1!=0){f1=k1->berechneFlaeche();}
    		else{f1=0;}
    		double f2;
    		Kreis* k2= dynamic_cast<Kreis*>(fig[i+1]);
    		Quadrat* q2=dynamic_cast<Quadrat*>(fig[i+1]);
    		Rechteck* r2=dynamic_cast<Rechteck*>(fig[i+1]);
    		if (q2!=0){f2=q1->berechneFlaeche();}
    		if (r2!=0){f2=r1->berechneFlaeche();}
    		if (k2!=0){f2=k1->berechneFlaeche();}
    		else{f2=0;}
    		if (f2>f1){index++;}
    		
    		}
        // Verschiebe Figuren
        fig[0]->verschiebe(10,10);
        fig[1]->verschiebe(10,10);
        fig[2]->verschiebe(10,10);
        fig[3]->verschiebe(10,10);
    
        // Gebe die Figuren auf der Konsole aus
        std::cout << fig[0]->asString() << std::endl;
        std::cout << fig[1]->asString() << std::endl;
        std::cout << fig[2]->asString() << std::endl;
        std::cout << fig[3]->asString() << std::endl;
    
        // Bereinige Speicher.
        delete fig[0];
        delete fig[1];
        delete fig[2];
        delete fig[3];
    }
    

    Ähm...jetzt bin ich baff...

    Bist Du sicher dass Du die Aufgabe richtig verstanden hast? Gibt es dazu einen Lehrer oder Prof, bei dem Du nachfragen kannst?

    Und noch eins:

    // Gebe die Figuren auf der Konsole aus
        std::cout << fig[0]->asString() << std::endl;
        std::cout << fig[1]->asString() << std::endl;
        std::cout << fig[2]->asString() << std::endl;
        std::cout << fig[3]->asString() << std::endl;
    

    Kennst Du einen Mechanismus in C++, der ohne copy&paste einen Programmabschnitt x-mal wiederholt?



  • Ich denke ich habe die Aufgabe gut verstanden 🙂

    Und noch eins:
    C++:
    // Gebe die Figuren auf der Konsole aus
    std::cout << fig[0]->asString() << std::endl;
    std::cout << fig[1]->asString() << std::endl;
    std::cout << fig[2]->asString() << std::endl;
    std::cout << fig[3]->asString() << std::endl;
    Kennst Du einen Mechanismus in C++, der ohne copy&paste einen Programmabschnitt x-mal wiederholt?

    Ja natürlich kenne ich da einen Mechanismus^^ Nur war die Aufgabe so gegeben.



  • Markus97 schrieb:

    Nur war die Aufgabe so gegeben.

    Vielleicht eine pädagogische Volte...

    Guten Rutsch jedenfalls! 🙂


Anmelden zum Antworten