2010-02-22 15 views
6

Ich habe dieses Problem für eine ziemlich lange Zeit - ich habe 2D-Array von fester Größe als ein Klassenmitglied.Übergabe Zeiger auf 2D-Array C++

class myClass 
{ 
public: 
     void getpointeM(...??????...); 
     double * retpointM(); 

private: 

    double M[3][3]; 

}; 

int main() 
{ 
    myClass moo; 
    double *A[3][3]; 

    moo.getpointM(A); ??? 
    A = moo.retpointM(); ??? 

} 

Ich würde Zeiger auf M Matrix außerhalb übergeben. Es ist wahrscheinlich sehr einfach, aber ich kann einfach nicht die richtige Kombination von & und * usw. finden.

Danke für Hilfe.

Antwort

9

double *A[3][3]; ist ein 2-dimensionales Array von double * s. Sie möchten double (*A)[3][3]; .

Dann beachten Sie, dass A und *A und alle die gleiche Adresse haben, nur verschiedene Typen.

ein typedef machen kann Dinge vereinfachen:

typedef double d3x3[3][3]; 

Dieses Wesen C++, sollten Sie die Variable als Verweis übergeben, nicht Zeiger:

void getpointeM(d3x3 &matrix); 

Sie brauchen jetzt nicht Pars zu verwenden, in Geben Sie Namen ein, und der Compiler stellt sicher, dass Sie ein Array der richtigen Größe übergeben.

+0

Sie sollten keine Referenzen verwenden "weil dies C++ ist" oder "nur weil Sie können". Verwenden Sie sie, wenn sie klarer sind als verfügbare Alternativen. –

+0

@Roger: ja, naja, hier ist es jedenfalls angebracht: v) – Potatoswatter

0

Die kurze Antwort ist, dass Sie ein double * zu Beginn des Arrays bekommen:

public: 
    double * getMatrix() { return &M[0][0]; } 

Außerhalb der Klasse, aber kann man nicht wirklich trivial die double * in einen anderen 2D-Array dreht direkt an zumindest nicht in einem Muster, das ich gesehen habe.

Sie könnten jedoch ein 2D-Array in main erstellen (double A [3] [3]) und das in eine getPoint-Methode übergeben, die die Werte in das übergebene Array kopieren könnte. Das würde Ihnen eine Kopie geben, die das sein könnte, was Sie wollen (anstelle der ursprünglichen, modifizierbaren Daten). Nachteil ist, dass Sie es natürlich kopieren müssen.

+0

Nein! Gib nicht auf! – Potatoswatter

0

In Ihrer main() Funktion:

double *A[3][3]; 

schafft ein 3x3-Array von double* (oder Zeiger auf Doppelzimmer). Mit anderen Worten, 9 zusammenhängende 32-Bit-Wörter des Speichers, um 9 Speicherzeiger zu speichern.

Es ist nicht notwendig, Kopie dieses Arrays in main() zu machen, es sei denn die Klasse wird zerstört, und Sie wollen immer noch auf diese Informationen zugreifen. Stattdessen können Sie einfach einen Zeiger auf den Anfang dieses Elementarrays zurückgeben.

Wenn Sie nur einen Zeiger auf einen internen Teilnehmer, zurückkehren möchten, müssen Sie nur wirklich einen einzigen Zeigerwert in main():

double *A; 

Aber, wenn Sie diesen Zeiger auf eine Funktion, vorbei sind und Sie müssen die Funktion den Wert zu aktualisieren, müssen Sie ein Doppelzeiger (die die Funktion den echten Zeigerwert zurück an den Anrufer zurück erlaubt:

double **A; 

Und innen getpointM() Sie können einfach A auf das innere Element Punkt (M):

getpointeM(double** A) 
{ 
    // Updated types to make the assignment compatible 
    // This code will make the return argument (A) point to the 
    // memory location (&) of the start of the 2-dimensional array 
    // (M[0][0]). 
    *A = &(M[0][0]); 
} 
+0

naja es scheint so, als ob das was ich wirklich machen wollte :) Aber immer noch mit fehler: kann 'double [3] [3]' nicht zu konvertieren 'double *' in Aufgabe – Moomin

+0

Entschuldigung mein Fehler - habe vergessen, ** in beiden Zeilen hinzuzufügen – Moomin

+2

Das ergibt für mich keinen Sinn. Das Mitglied wird als "double M [3] [3]" deklariert. Die Zuordnung '* A = M' wird einfach nicht kompiliert, da die linke Seite' double * 'und die rechte Seite' double (*) [3] 'ist. Diese Typen sind nicht kompatibel. – AnT

0
class myClass 
{ 
public: 
     void getpointeM(double *A[3][3]) 
     { 
      //Initialize array here 
     } 

private: 

    double M[3][3]; 

}; 

int main() 
{ 
    myClass moo; 
    double *A[3][3]; 

    moo.getpointM(A); 
} 
3

Ihre Absicht ist nicht klar. Was soll getpointeM tun? Einen Zeiger auf die interne Matrix zurückgeben (durch den Parameter) oder eine Kopie der Matrix zurückgeben?

einen Zeiger zurückzukehren, können Sie dies tun

// Pointer-based version 
... 
void getpointeM(double (**p)[3][3]) { *p = &M; } 
... 
int main() { 
    double (*A)[3][3]; 
    moo.getpointM(&A); 
} 

// Reference-based version 
... 
void getpointeM(double (*&p)[3][3]) { p = &M; } 
... 
int main() { 
    double (*A)[3][3]; 
    moo.getpointM(A); 
} 

Für retpointM die Erklärung aussehen würde als

... 
double (*retpointM())[3][3] { return &M; } 
... 
int main() { 
    double (*A)[3][3]; 
    A = moo.retpointM(); 
} 

Dies folgt, ist ziemlich schwierig, wenn zu lesen. Sie können es viel klarer aussehen, wenn Sie Typ In diesem Fall

typedef double M3x3[3][3]; 

ein typedef-Namen für das Array verwenden die obigen Beispiele in

// Pointer-based version 
... 
void getpointeM(M3x3 **p) { *p = &M; } 
... 
int main() { 
    M3x3 *A; 
    moo.getpointM(&A); 
} 

// Reference-based version 
... 
void getpointeM(M3x3 *&p) { p = &M; } 
... 
int main() { 
    double (*A)[3][3]; 
    moo.getpointM(A); 
} 

// retpointM 
... 
M3x3 *retpointM() { return &M; } 
... 
int main() { 
    M3x3 *A; 
    A = moo.retpointM(); 
} 
0

Sie den Code in Anspruch nehmen verwandeln wollen in Ihre Hauptfunktion, die mit dem 2D-Array von Doubles arbeitet und diese als Member-Funktion in myClass verschiebt. Sie müssten nicht nur mit der Schwierigkeit fertig werden, einen Zeiger für dieses 2D-Array zu übergeben, sondern Code, der sich außerhalb Ihrer Klasse befindet, würde nicht mehr die Details darüber benötigen, wie Ihre Klasse A implementiert, da sie jetzt eine Funktion aufrufen würden myClass und lass das die Arbeit machen. Wenn Sie beispielsweise später entscheiden, variable Dimensionen von A zuzulassen und das Array durch vector von vectors ersetzen möchten, müssen Sie keinen Funktionscode neu schreiben, damit er funktioniert.

0

Machen Sie M öffentlich statt privat. Da Sie den Zugriff auf M über einen Zeiger erlauben wollen, ist M sowieso nicht gekapselt.

struct myClass { 
    myClass() { 
    std::fill_n(&M[0][0], sizeof M/sizeof M[0][0], 0.0); 
    } 
    double M[3][3]; 
}; 

int main() { 
    myClass moo; 
    double (*A)[3] = moo.M; 
    double (&R)[3][3] = moo.M; 

    for (int r = 0; r != 3; ++r) { 
    for (int c = 0; c != 3; ++c) { 
     cout << A[r][c] << R[r][c] << ' '; 
     // notice A[r][c] and R[r][c] are the exact same object 
     // I'm using both to show you can use A and R identically 
    } 
    } 

    return 0; 
} 

Ich würde in der Regel bevorzuge R über A, weil die alle Längen sind festgelegt (A möglicherweise zu einem double[10][3] zeigen könnte, ob das eine Anforderung war) und die Referenz wird in der Regel zu einem klareren Code führen.