class array und array in der class verändern

  • C/C++

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • class array und array in der class verändern

    Hallo ich habe folgendes Problem und zwar erstelle ich zubeginn meines Programmes eine Klasse und inerhalb dieser Klasse möchte ich mit einer Methode ein Array verändern was den typ dieser Klasse enspricht . Nun stellt sich das Problem , dass ich das Array ja erst nach der Klasse erstellen kann das dann aber beim Compiliren das Array in der Methode nicht erkennt . Ich hoffe einer von euch kann mir helfe :)
  • Das array soll durch eine Methode in der Klasse und im Hauptprogramm verändert werden können deswegen deklarire ich es zwischen der Klasse und dem Hauptprogramm aber dann sagt mir der Compieler halt Error weil er das Array ja noch nicht deklariert hat während er die Klasse umwandelt . Also die Reihnfolge ist bei mir Klasse => Array => Hauptprog was wenn die Klasse keine Methode mit dem Array hätte ja Funktionier würde ?( ?( ?(



    Quellcode

    1. include blalba
    2. class test {
    3. public : int wert;
    4. void methode{
    5. array[0] = 3;
    6. };
    7. }
    8. int array[10];
    9. main(bla)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Mapman ()

  • Mapman schrieb:

    Kann den über eine Referenz das Array auch verändert werden ? Ich dachte darüber kann man es nur Abfragen ?


    Man übergibt Arrays nicht über Referenzen sondern über einen Pointer. Naja man übergibt eigentlich nur einen Pointer, der aufs erste Element des Arrays zeigt:

    GML-Quellcode

    1. int g_array[100];
    2. void Foo(int* bar)
    3. {
    4. bar[0] = 1;
    5. bar[42] = 87;
    6. }
    7. void Foobar()
    8. {
    9. Foo(g_array);
    10. }
    Alles anzeigen

    © 2008 by Teamgrill Productions
  • Mapman schrieb:

    Und so ein Pointer ist doch dann eine Referenz für das Array ?


    Jein, Pointer != Referenz. Eine Referenz ist wieder etwas anderes. Mit Pointern kann man viel mehr Blödsinn anstellen (Stichwort Pointerarithmetik).
    Sowas geht zum Beispiel nicht mit Referenzen:

    GML-Quellcode

    1. #include <cstring>
    2. #include <iostream>
    3. int main()
    4. {
    5. int array[100];
    6. memset(array, 0, 100 * sizeof(int));
    7. int* ptr;
    8. ptr = array + 5;
    9. ptr++;
    10. ptr[3] = 1;
    11. std::cout << array[9] << std::endl;
    12. int& myref = array[9]; // Muss hier definiert werden, bei Pointern ist das egal
    13. myref = 2;
    14. std::cout << array[9] << std::endl;
    15. return 0;
    16. }
    Alles anzeigen

    © 2008 by Teamgrill Productions
  • Bei multidimensionalen Arrays wird die ganze Pointergeschichte etwas schwieriger, ich weiß jetzt ehrlich gesagt auch nicht wie man einen Pointer zu einem Stack-Array (so eins wie in meinem obigen Beispiel) bekommt. Wenn du es auf dem Heap erstellst, geht es einfacher:

    GML-Quellcode

    1. int** array = new int*[100];
    2. for(int i = 0; i < 100; i++)
    3. int[i] = new int[100];


    Das ist die ganze Mühe aber meiner Ansicht nach nicht wert. Deshalb verwende ich immer eindimensionale Arrays:

    GML-Quellcode

    1. int array[100*100];
    2. // [80][30] ändern
    3. array[30 * 100 + 80] = 1;

    © 2008 by Teamgrill Productions
  • Mapman schrieb:

    Und so ein Pointer ist doch dann eine Referenz für das Array ? also so wurde mir gelehrt 8o aber danke für die Antwort :D


    Dann hat derjenige, der dir das erklärt hat, entweder keine Ahnung, oder sich missverständlich ausgedrückt, oder ihr habt euch über eine andere Sprache unterhalten.

    Um das für C++ einmal klarzustellen: Es gibt drei Konzepte, um Daten anzusprechen: Variablen, Refrenzen und Zeiger (Pointer).

    C-Quellcode

    1. // eine Variable
    2. int a = 42;
    3. // eine Referenz
    4. int & b = a;
    5. // ein Zeiger
    6. int * c = &a;


    Der "Normalfall" sind Variablen. Wann immer du dir etwas speichern möchtest, legst du dir eine solche an und schreibst den Wert rein. Dabei geschehen bei der Deklaration zwei Dinge: 1.: Es wird Platz im Speicher reserviert, an dem der Wert der Variable abgelegt werden kann, 2.: Der Name der Variable wird mit der Adresse des reservierten Platzes im Speicher assoziiert. D.h. für obiges Beispiel: Wannimmer du auf a schreibst oder a in einen Ausdruck setzt, wir auf den Teil des Speichers zugegriffen, der bei der Deklaration von a reserviert wurde.

    Eine Referenz ist quasi nur ein Synonym für eine Variable, d.h. im Gegensatz zu der Deklaration von a wird bei der Deklaration von b kein eigener Speicher für Werte reserviert, sondern auf die gleiche Adresse verwiesen, wie bei a.
    Danach sind a und b quasi beliebig gegeneinander austauschbar, d.h. wenn ich auf a schreibe, kann ich das geschriebene danach von b lesen und umgekehrt.

    Ähnlich wie eine Referenz speichert auch ein Zeiger keine Werte, sondern Adressen. Im Gegensatz zu Referenzen lässt sich diese aber beliebig ändern. D.h. während b für den Rest seiner Lebenszeit mit der Adresse von a verheiratet ist, kann c noch auf beliebige andere Stellen im Speicher zeigen. Und wenn man direkt auf c zugreift, erhält man auch nicht den Wert, der dort gespeichert ist, sondern die Adresse selbst. Will man an den Wert ran (oder einen neuen Wert schreiben), muss man immer erstmal dereferenzieren:

    C-Quellcode

    1. *c = 23;


    Um nun wieder auf das Array zurückzukommen: Um zu wissen, wie du ein Array übergeben, lesen oder verändern kannst, solltest du erstmal wissen, was ein Array in C(++) eigentlich ist: Ein Array ist auch nur ein Zeiger. D.h. wenn du eine Variable foo vom Typ int[] anlegst, hast du mit foo auch nur einen Zeiger auf die Basisadresse dieses Arrays in der Hand, also auf das erste Feld in diesem Array. Du kannst also z.B. folgendes machen:

    C-Quellcode

    1. void foo(int * a)
    2. {
    3. a[0] = 23;
    4. a[7] = 42;
    5. }
    6. void bar()
    7. {
    8. int b[10];
    9. foo(b);
    10. }
    Alles anzeigen


    Auch solltest du wissen, was der []-Operator eigentlich macht: Im Grunde handelt es sich dabei nur um syntaktischen Zucker für den Umgang mit Zeigern. Folgende Zeilen sind äquivalent:

    C-Quellcode

    1. // a ist ein Array oder Zeiger; b ist eine Zahl; c ist vom Typ des Arrays
    2. a[b] = c;
    3. b[a] = c;
    4. *(a+b) = c;


    Die letzte Zeile möchte ich nochmal kurz erklären: Wenn du auf einen Zeiger eine Zahl addierst, addierst du nicht die Zahl selbst, sondern das Produkt aus dieser Zahl und der Größe des Datentyps. D.h. wenn der Typ von c z.B. vier Byte groß ist, wird auf a das Vierfache von b addiert, und auf die resultierende Adresse zugegriffen.

    Deswegen reicht es, nur die Basisadresse eines Arrays an Funktionen zu übergeben, damit diese drauf arbeiten können.

    Edit: Meine Fresse, bin ich langsam...

    Edit2: @Soul Reaver: Statische zweidimensionale Arrays erstellt man genau so, wie man drauf zugreift:

    C-Quellcode

    1. int foo[100][200];
    2. foo[2][3] = 42;
  • Soul Reaver schrieb:

    CAS schrieb:


    @Soul Reaver: Statische zweidimensionale Arrays erstellt man genau so, wie man drauf zugreift:

    C-Quellcode

    1. int foo[100][200];
    2. foo[2][3] = 42;

    Schon klar, aber man kann sie nicht als int** übergeben.
    Btw: Du bist echt langsam ;)


    Könnte daran liegen, dass ein int[m][n] kein int** ist. Bei int i[10][20] hebst du direkt 10*20 ints aus dem Speicher, die als Basisadresse das erste Element bekommen; bei int ** i holst du dir erstmal nur ein Zeigerarray, bei dem die jedem Feld die Adresse der Zeile geben musst, die eigentlich dahinter steckt. D.h. beim ersten hast du mit dem Aufruf i[x][y] die "direkte" Adressierung *(i + y*20 + x), beim zweiten die "indirekte" Adressierung *(*(i+x) + y). Weil du also mit beiden Typen unterschiedlich umgehen musst, werden sie vom Compiler auch als unterschiedlich betrachtet.

    Und aus der ersten Adressierungsart folgt auch, wie so ein Array an eine Funktion übergeben werden muss: Wenn du nur die Basisadresse übergibst, kann zur Laufzeit lediglich ermittelt werden, wo der Block beginnt (Basisadresse), und wie groß er ist ("Länge" * "Breite" * Größe des Datentyps), aber nicht, wie genau Länge und Breite festgelegt wurden (ist es nun ein 2*3-Array oder ein 3*2-Array). Um aber bei der Angabe i[x][y] die richtige Zelle zu erwischen, muss bekannt sein, wie "lang" und "breit" das Array ist, und dazu muss dann mindestens eine Dimension schon in der Funktion angegeben werden.

    Und wenn du mal versuchst, ein int[m][n] an ein int** zuzuweisen, wird dir die Compilermeldung auch sagen, welche Dimension er haben will; im Falle des gcc ist es die zweite. Eine Funktion, um so ein Array zu übergeben, sieht also so aus:

    C-Quellcode

    1. void foo(int (*a)[20])
    2. {
    3. a[2][3] = 42;
    4. }
    5. // alternativ kann man auch bede Dimensionen fixieren
    6. void bar(int a[10][20])
    7. {
    8. a[2][3] = 42;
    9. }
    10. void baz()
    11. {
    12. int i[10][20];
    13. foo(i);
    14. bar(i);
    15. }
    Alles anzeigen


    Das erfordert aber, dass du für jede mögliche Länge der zweiten Dimension eine eigene Funktion schreibst.

    Wie gut, dass es Templates gibt:

    C-Quellcode

    1. template <int S> // S für size
    2. void foo(int (*a)[S])
    3. {
    4. a[2][3] = 42;
    5. }


    An diese Funktion (d.h. Instanzen von ihr) lassen sich nun beliebige zweidimensionale statische Arrays übergeben.
  • Benutzer online 1

    1 Besucher

  • Tags