Modifizierung eines Objektes in einer Klasse



  • Hallo alle zusammen!

    Ich habe eine Klasse geschrieben, in dessen Bauplan die Erstellung eines TImage enthalten ist. Die Initialisierung und das Laden der Bilder aus meiner resource funktioniert wunderbar, allerdings scheine ich in Objektorientierung ein leichtes Defizit zu haben, denn ich bin nicht in der Lage nun dem Bild zum Beispiel einen neuen Abstand von Links zu geben. Wenn ich die Funtkion set_hpos(10); aufrufe kommt beim Ausführen folgende Windows-Fehlermeldung:

    Zugriffsverletzung bei Adresse 0045F148 in Modul 'autorennen_beta2.exe'. Lesen von Adresse 00000048.

    edit
    Das Problem ist nur das Aufrufen der Funktion in blauer_racer->set_hpos(50);. Wenn ich das auskommentiere funktioniert der constructor.
    /edit

    Weiß jemand von Euch, was ich da falsch gemacht habe?

    Gruß
    Kasimir

    Unit1.cpp

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    
    TRacer::TRacer(String bildname, int hpos, int vpos) {
    	TImage *racerpic = new TImage(Form1);
    	racerpic->Parent = Form1;
    	racerpic->Top = vpos;
    	racerpic->Left = hpos;
    	racerpic->Transparent = true;
    	racerpic->Visible = true;
    	racerpic->AutoSize = true;
    	racerpic->Picture->Bitmap->LoadFromResourceName(int(HInstance), bildname);
    }
    
    void TRacer::set_hpos(int wert) {
    	racerpic->Left=wert;
    }
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
    TRacer* blauer_racer = new TRacer("AUTO_BLAU",20,150);
    blauer_racer->set_hpos(50);
    }
    //---------------------------------------------------------------------------
    

    Unit1.h

    //---------------------------------------------------------------------------
    
    #ifndef Unit1H
    #define Unit1H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <ExtCtrls.hpp>
    #include <GIFImg.hpp>
    #include <MPlayer.hpp>
    #include <ComCtrls.hpp>
    //---------------------------------------------------------------------------
    class TRacer
    {
    	private:
    		bool winner;
    		int hpos, vpos;
    		String bildname;
    
    	public:
    		TRacer(String,int,int);
    		void set_hpos(int);
    		TImage *racerpic;
    };
    
    class TForm1 : public TForm
    {
    __published:	// IDE-verwaltete Komponenten
    	void __fastcall FormCreate(TObject *Sender);
    private:	// Benutzer Deklarationen
    public:		// Benutzer Deklarationen
    	__fastcall TForm1(TComponent* Owner);
    	TRacer *blauer_racer;
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif
    


  • Hallo

    Im Konstruktor von TRacer erstellst du zwar eine Instanz von TImage, aber du weist nur dem lokalen Zeiger racerpic die Adresse davon zu. Die Membervariable racerpic bekommt dadurch die Adresse nicht, und bleibt uninitialisiert. Deshalb die Zugriffsverletzung. Zur Behebung must du nur statt einer lokalen die Membervariable ansprechen :

    racerpic = new TImage(Form1);
    

    Desweiteren solltest du unbedigt noch einen Konstruktor für TForm1 erstellen, um die TRacer-Instanz wieder zu löschen.

    bis bald
    akari



  • Unglaublich! 🙂 Vielen Dank es geht!
    Aber inwiefern ich einen Konstruktor für TForm1 erstellen soll verstehe ich gerade nicht... 🙄



  • Hallo

    Sorry, ich meinte natürlich Destruktor.

    bis bald
    akari



  • Ich muss leider zugeben, dass ich ebenfalls nicht weiß wie denn ein Destruktor für TForm1 aussehen könnte! 🙄

    Gruß
    Kasimir



  • Kasimir87 schrieb:

    Ich muss leider zugeben, dass ich ebenfalls nicht weiß wie denn ein Destruktor für TForm1 aussehen könnte! 🙄

    Gruß
    Kasimir

    Ich hoffe aber, dass du weißt, was ein Destruktor ist, oder?

    TForm1::~TForm1()()
    {
        delete racerpic;
    }
    

    Ansonsten, solltest du dich dran gewöhnen die Variablennamen in Englisch zu bennenen.

    Gruß



  • jesus was black schrieb:

    TForm1::~TForm1()()
    {
        delete racerpic;
    }
    

    Warst du sehr in Eile ? 😉

    TForm1::~TForm1()
    {
        delete racerpic;
    }
    


  • Also der Destruktor zerstört das Objekt und gibt den Speicher wieder frei, aber in diesem Falle will mein Destruktor einfach nicht... destruktieren...
    Ich bekomme immer die Fehlermeldung "Virtuelle Funktion '~TForm1::TForm1()' verursacht Konflikte mit der Basisklasse 'TForm'".
    Ich habe den Destruktor in den public-bereich der TForm1-Klasse gesetzt und nunja. Irgendwie scheint das nicht ganz richtig so zu sein 😕

    Gruß
    Kasimir



  • Hallo

    Der Destruktor einer VCL-Klasse muß wie der Konstruktor immer als __fastcall deklariert werden.

    bis bald
    akari



  • Nun funktioniert es, allerdings nur wenn ich den speziell erschaffenen racer anspreche und nicht allgemein das racerpic. racerpic ist ja ein Objekt innerhalb der Klasse TRacer und von TRacer gibt es in meinem falle 4 objekte. Hab ich das richtig verstanden, dass der Destruktor für die Racer ist oder tatsächlich für das Bild-Objekt im Racer-Objekt?

    class TForm1 : public TForm
    {
    __published:	// IDE-verwaltete Komponenten
    	TTimer *Timer1;
    	TButton *startbutton;
    	TLabel *Label1;
    	TLabel *geld;
    	TLabel *Label3;
    	TEdit *einsatz;
    	TLabel *statusmeldung;
    	TComboBox *favourit;
    	TImage *strasse;
    	TImage *ziel;
    	TImage *ton;
    	void __fastcall startbuttonClick(TObject *Sender);
    	void __fastcall FormCreate(TObject *Sender);
    	void __fastcall strasseClick(TObject *Sender);
    	void __fastcall favouritChange(TObject *Sender);
    	void __fastcall Timer1Timer(TObject *Sender);
    	void __fastcall tonClick(TObject *Sender);
    private:	// Benutzer Deklarationen
    public:		// Benutzer Deklarationen
    	__fastcall TForm1(TComponent* Owner);
    	__fastcall TForm1::~TForm1()
    	{
    		delete gruener_racer;
    		delete blauer_racer;
    		delete oranger_racer;
    		delete roter_racer;
    	}
    	TRacer *gruener_racer;
    	TRacer *blauer_racer;
    	TRacer *oranger_racer;
    	TRacer *roter_racer;
    };
    

    Ist es überhaupt nötig, dass ich jedes zu zerstörende Objekt benenne oder kann man das irgendwie ausdrücken, dass alle erschaffenen Objekte vom Typ TRacer zerstört werden sollen?

    Gruß
    Kasimir



  • naja du könnest auch im Konstruktor von Form1 folgendes machen:

    #include <memory>       //for STL auto_ptr class
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
    static std::auto_ptr<TRacer> _MyRacerCleaner_gruen(gruener_racer = new TRacer);
    static std::auto_ptr<TRacer> _MyRacerCleaner_blau(blau_racer = new TRacer);
    static std::auto_ptr<TRacer> _MyRacerCleaner_orange(orange_racer = new TRacer);
    static std::auto_ptr<TRacer> _MyRacerCleaner_rot(rot_racer = new TRacer);
    }
    

    dann brauchst du gar keinen Destruktor



  • Ah danke, auto_ptr gegoogelt und gleich fündig geworden. Was genau das ist, was ich da denn allerdings mache muss ich mir erstmal erarbeiten 😉

    Vielen Dank für die Hilfe von Euch!

    Gruß
    Kasimir


Anmelden zum Antworten