Zum Inhalt springen

Problem mit einer Klasse und Arraywerte


Empfohlene Beiträge

Geschrieben (bearbeitet)

Hallo,

wieder ein weiteres Problem das mich in meiner anfänglichen Zeit überfordert.

Ich habe folgende Struktur:

Hauptprogramm -> externe Klasse (Header u. Rumpf seperat) -> einmalige(!) Berechnungen der Konstruktionsdaten im Array speichern -> Arraydaten sollen nach dem einmaligen Aufruf des If Blocks weiter verwendet werden zum zeichnen eines Objekts -> Rückkehr zum Hauptprogramm ... Buffer leeren und auf Bildschirm ausgeben. (und wieder von vorne)

Mein Problem sind nun die Daten in dem Array. In Delphi hab ich globale, dynamische Arrays angegeben dessen Größe und Werte nur einmal zur Laufzeit per if(done == false) ... ...Berechnungen... ... Ende des Blocks ... (done = true) berechnet werden und danach griff die Zeichenroutine immer wieder auf die Werte im Array zurück.

Das Problem ist ja das die Variablen in C++ die in einen Anweisungsblock deklariert wurden ja nur für diesen gelten. Hab da was mit Zeigern gelesen und die Werte im Heap speichern, aber da blick ich noch nicht so ganz durch

und ich wollte es vermeiden ein Array vorher im Hauptprogramm zu deklarieren.

Wie gehe ich nun am besten ran an mein Problem?

Noch was: Wenn ich eine kleine Testroutine in die Klasse schreibe die mir nur ein Viereck zurückgeben soll muss ich auch einen Pointer auf die Klasse angeben da mir das Programm, wenn ich eine Variable verwende, nur einen Grafikfehler ausgibt. Wie ist das zu erklären?

Danke schonmal für eure Hilfe.

Bearbeitet von Mr. Miyagi
Syntaxfehler
Geschrieben

Da niemand antwortet, habe ich mich bestimmt nur umständlich ausgedrückt.

Was ich machen will:

Ich will in einer Klasse ein Array erstellen. Man übergibt Werte durch eine Funktion, die dann zur Größenbestimmung des Arrays dienen (nicht das Problem). Danach wird das Array einmalig(!) mit Daten gefüllt. Nun ruft eine andere Funktion (in einer Endlosschleife) immer wieder die Daten aus dem Speicher ab. Die Schleife wird erst durch Tastendruck beendet.

Meine Lösungsidee:

Ich erstelle das Array im Heap und die Funktion die, die Daten braucht bekommt sie über Zeiger auf die Werte.

Mein Problem:

Wie würde der Syntax dazu aussehen und vorallem, warum ?!

Ich habe zwar C++ in 21 Tagen, aber das behandelt Zeiger und Arrays seperat und damit kenne ich keine Kombination aus beiden.

Geschrieben

In C++ solltest du Arrays nach Möglichkeit vermeiden.

Meistens ist es besser, std::vector zu benutzen. Diese Klasse stellt einen zusammenhängenden Speicher für Objekte desselben Typs bereit, kann dynamisch wachsen und kümmert sich selbst um die Speicherverwaltung.

Geschrieben

Danke für deine Information.

Ich kenne mich zwar überhaupt nicht aus mit std::vector,

aber ich versuche mal etwas im Internet dazu zu finden.

Ist Vector, wenn ich Daten hinein schreibe dann im Heap abgelegt ?

Mir geht es ja darum, dass ich ich die Klasse in der das Array erstellt wird

von "außen" aufrufe, es erstelle, mit Daten fülle, zum Hauptprogramm zurück

kehre und dann durch eine Endlosschleife nur wieder die Daten abfrage.

Oder sind die Daten nach Aufruf der Funktion aus der Klasse und

Rückkehr zum Hauptprogramm durch den Destructor wieder gelöscht ?

Geschrieben
Ist Vector, wenn ich Daten hinein schreibe dann im Heap abgelegt ?

Mir geht es ja darum, dass ich ich die Klasse in der das Array erstellt wird

von "außen" aufrufe, es erstelle, mit Daten fülle, zum Hauptprogramm zurück

kehre und dann durch eine Endlosschleife nur wieder die Daten abfrage.

Ein Vector legt seine Daten im Free Store ab, solange du nichts anderes festlegst. Der Free Store entspricht dem Heap in C. Viele Compiler unterscheiden das gar nicht.

Die Lebenszeit der Objekte ist aber an die Lebenszeit des Vector gekoppelt. Wenn der Vector allerdings ein Member deiner Klasse ist, existiert er so lange, wie die Instanz der Klasse existiert.

Geschrieben

Da ich mal annehme das die Instanz einer Klasse sich genauso verhällt wie

eine lokale Variable. Sprich nur für den Anweisungsblock in dem sie deklariert

ist auch gültig ist, werde ich da keine weiteren Probleme haben. (hoffe ich

zumindest ^^) Falls meine Annahme nicht richtig ist, berichtigt mich bitte.

Es könnte ja auch sein, dass die Instanz erst ihre Gültigkeit verliert in dem

man explizit den Destructor aufruft.

Ansonsten sag ich schon mal Danke.

Geschrieben

Wenn du eine Instanz einer Klasse als lokale Variable anlegt, dann verliert sie ihre Lebenszeit, wenn der Block, in dem sie definiert ist, beendet ist. Wenn du die Instanz mit new anlegst, endet ihre Lebenszeit, wenn du delete aufrufst.

Es könnte ja auch sein, dass die Instanz erst ihre Gültigkeit verliert in dem

man explizit den Destructor aufruft.

Das macht man eigentlich nie. Den Destruktor darf man nur dann explizit aufrufen, wenn man placement-new benutzt hat, um die Instanz zu erzeugen.
Geschrieben

Könntest du dich etwas präziser ausdrücken. Wenn ich dich richtig verstanden habe, würde ich dies vorschlagen:

Wenn du die Kapselung konsequent anwendest, ist das Array nur über die beiden Lese- und Schreibfunktionen manipulierbar. Das Feld, in dem du die Daten abspeicherst, kannst du im Konstruktor allokieren(Speicherplatz festlegen), und im Destruktor wieder freigeben.

VC++ erlaubt auch Konstruktoren mit Argumenten.

Das ist ein Beispiel in VC++


/* header */


class daten

{

public:

     daten();                 

     daten(int groesse)

    ~daten();

private:

     int* zeiger;

public:

    void ErstelleDaten(int groesse);

    void ZerstoereDaten(); 

    int LeseDaten(int pos);

    void SchreibeDaten(int pos, int zahl);

};


daten : daten()

{

}


daten : daten(int groese)

{

zeiger=malloc(groesse); /Nur Anhalt malloc muß nicht stimmen!

}


daten:~daten()

{

free(zeiger);

}

Das wendest du dann so an:

main()

{

      int eingabe;      

      daten feld;    / Datenfeld lebt solange wie main()

      int anzahl;

      do

      {

                anzahl=feldgroesse();                 

                feld.ErstelleDaten(anzahl);

                Dateneingeben(feld);

                Zeichen(feld);

                feld.ZerstoereDaten();


                printf("Nochmal?(0/1);

                eingabe=getch();

      } while(eingabe!=0); 

}

Das sollte es in etwa sein.

LG

Andre'

Geschrieben

Danke, hab das Problem schon genauso gelöst. ^^

Nun hab ich aber ein anderes Problem. Ich kann meine Zeiger und Variablen nur Global deklarieren.

Wenn ich sie im privaten Teil der Klasse deklariere, kennt meine Cpp Datei dazu zwar die Variablen

und schreibt auch die richtigen Werte in diese, nur kann ich diese dann nicht verwenden. Immer

wenn ich es versuche, dann blitzt kurz mein Fenster auf und ist auch gleich wieder weg.

einfaches Beispiel

if (done==FALSE)

{

...

}

Dann wird das Programm einfach beendet obwohl done eine boolischer Variable ist und ich

vorher in einer anderen Prozedur done den Wert false zugewiesen habe. Deklariere ich done

nun global in der Cpp Datei funktioniert alles super. So gesehen funktioniert also alles. Mein

schlaues Buch sagt mir aber, dass man globale Variablen möglichst vermeiden sollte und

daran will ich mich auch halten. :D

Geschrieben

Ich hab nun ein kleines Beispiel geschrieben in dem das Problem auftritt. Ich

habe erst versucht eine normale Klasse zu erstellen, doch die lief einwandfrei.

Der Fehler tritt also nur auf wenn ich OpenGL und SDL verwende und dann im

Publicteil die Variablen deklariere und versuche diese zu benutzen.

Ich hänge einfach mal das Projekt von Code::Blocks an. Dort wird nur ein

Vierreck mit einer einfachen Textur gerendert. Hab jeglichen Zusatz weggelassen

um es so übersichtlich wie möglich zu halten. Wichtig ist noch zu sagen, dass

man auf jedenfall die SDL Bibliotheken braucht um das Projekt überhaupt compilieren

zu können. Einmal das normale SDL Developement Paket und SDL Image. Die beiden

Pakete sind aber in der Zip enthalten.

In Code::Blocks muss man dann im Linker noch folgende Bibliotheken angeben:

-lmingw32 -lSDLMain -lSDL -lopengl32 -lglu32 -lSDL_image

Hoffe ihr könnt mir helfen. :)

Beispiel.zip

Geschrieben

Das habe ich auch noch nicht erlebt, dass jemand ein Minimalbeispiel von 1,6 MByte abliefert :eek

Zum Glück lässt sich das Problem auch leicht erkennen, ohne das Projekt kompilieren zu müssen:

    Test* use;
use->draw(a,move);
[/code]

Das ist Blödsinn. use ist ein uninitialisierter Zeiger. Du erstellst nirgends ein Objekt der Klasse Test.

Der Code verursacht undefiniertes Verhalten, da kann alles passieren.

Geschrieben

Das ist nur 1,6 MB groß weil die SDL Bibliothek noch beiliegt. :D

Ich wollte ja nur das Gesuche nach den Dateien vermeiden.

Ja ehm. Wenn der Zeiger nicht richtig ist ... was dann?

Wie muss ich das denn richtig initialisieren?

Ich hoffe mal das der Fehler darauf beruht, aber wenn ich

eine Klasse genauso aufrufe die nicht SDL verwendet dann

geht das trotzdem.

Geschrieben
Ja ehm. Wenn der Zeiger nicht richtig ist ... was dann?

Wie muss ich das denn richtig initialisieren?

Du brauchst eine Instanz dieser Klasse. Die solltest du natürlich nicht in deiner Render-Funktion erzeugen, denn dann hättest du ja bei jedem Durchlauf eine neue.

Eine Instanz legst du durch

Test use;
oder, wenn eine Lebenszeit über den enthaltenen Block hinaus erforderlich ist, durch
Test* use = new Test;

an.

Ich hoffe mal das der Fehler darauf beruht, aber wenn ich eine Klasse genauso aufrufe die nicht SDL verwendet dann

geht das trotzdem.

Das ist das Schöne an undefiniertem Verhalten: Es kann alles passieren. Daraus, dass etwas funktioniert, darfst du nicht folgern, dass der Code richtig ist.

Dein uninitialisierter Zeiger zeigt irgendwo in den Speicher. Wenn das Programm dann dort versucht, Werte abzulegen oder auszulesen, kann das zufällig gut gehen oder auch dein Programm abstürzen lassen.

Geschrieben (bearbeitet)

Es funktioniert. :D

Es hat tatsächlich am dem undefinierten Pointer gelegen.

Das ist das Schöne an undefiniertem Verhalten: Es kann alles passieren. Daraus, dass etwas funktioniert, darfst du nicht folgern, dass der Code richtig ist.

Den Satz vergess ich definitiv nicht. ^^

Dann bedanke ich mich nochmal für eure guten Tipps und die Hilfe.

mfg Mr. Miyagi

Bearbeitet von Mr. Miyagi

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...