2010-02-22 5 views
6

Je rencontre ce problème depuis un certain temps. J'ai défini un tableau 2D de taille en tant que membre de la classe.Passage du pointeur sur le tableau 2D 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(); ??? 

} 

Je voudrais passer le pointeur à l'extérieur M matrice. C'est probablement très simple, mais je ne peux pas trouver la bonne combinaison de & et * etc

Merci pour l'aide.

Répondre

9

double *A[3][3]; est un tableau à deux dimensions de double * s. Vous voulez double (*A)[3][3]; .

Ensuite, notez que A et *A et ont tous la même adresse, mais seulement des types différents.

Faire typedef peut simplifier les choses:

typedef double d3x3[3][3]; 

Cet être C++, vous devez passer la variable par référence, pointeur non:

void getpointeM(d3x3 &matrix); 

Maintenant, vous n'avez pas besoin d'utiliser parens dans tapez les noms, et le compilateur s'assure que vous passez un tableau de la bonne taille.

+0

Vous ne devriez pas utiliser les références "parce que c'est C++" ou "juste parce que vous pouvez". Utilisez-les quand ils sont plus clairs que les alternatives disponibles. –

+0

@Roger: oui, eh bien, il est approprié ici, de toute façon: v) – Potatoswatter

0

La réponse courte est que vous pouvez obtenir un double * au début du tableau:

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

En dehors de la classe, cependant, vous ne pouvez pas vraiment tourner trivialement le double * dans un autre tableau 2D directement, à moins dans un modèle que j'ai vu utilisé.

Vous pouvez cependant créer un tableau 2D dans main (double A [3] [3]) et passer à dans une méthode getPoint, qui pourrait copier les valeurs dans le tableau transmis. Cela vous donnerait une copie, ce qui pourrait être ce que vous voulez (au lieu de l'original, modifiable, données). L'inconvénient est que vous devez le copier, bien sûr.

+0

Non! n'abandonne pas! – Potatoswatter

0

Dans votre fonction main():

double *A[3][3]; 

crée un tableau 3x3 de double* (ou des pointeurs à double). En d'autres termes, 9 mots de mémoire contigus de 32 bits pour stocker 9 pointeurs de mémoire.

copie de ce tableau dans main() sauf si la classe va être détruite, et vous souhaitez toujours accéder à cette information. Au lieu de cela, vous pouvez simplement renvoyer un pointeur au début de ce tableau de membres.

Si vous ne souhaitez que retourner un pointeur vers un membre de la classe interne, vous ne vraiment besoin d'une seule valeur de pointeur dans main():

double *A; 

Mais, si vous passez ce pointeur à une fonction et vous besoin de la fonction de mettre à jour sa valeur, vous avez besoin d'un double pointeur (ce qui permettra à la fonction de retourner la réelle valeur de pointeur à l'appelant:

double **A; 

Et à l'intérieur getpointM() vous pouvez simplement le point A à l'élément interne (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

Eh bien, il semble que c'est la chose que je voulais vraiment faire :) Mais toujours avec erreur: ne peut pas convertir 'double [3] [3]' 'double *' dans la tâche – Moomin

+0

désolé mon erreur - j'ai oublié d'ajouter ** dans les deux lignes – Moomin

+2

Cela n'a tout simplement aucun sens pour moi. Le membre est déclaré «double M [3] [3]». L'assigment '* A = M' ne compilera tout simplement pas, car le côté gauche est' double * 'et le côté droit 'double (*) [3]'. Ces types ne sont pas compatibles. – 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

Votre intention est pas claire. Que doit faire getpointeM? Renvoie un pointeur vers la matrice interne (via le paramètre) ou renvoie une copie de la matrice?

Pour retourner un pointeur, vous pouvez le faire

// 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); 
} 

Pour retpointM la déclaration se présente comme suit

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

Ce qui est assez difficile à lire cependant. Vous pouvez le faire paraître beaucoup plus clair si vous utilisez un typedef-nom pour votre type tableau

typedef double M3x3[3][3]; 

Dans ce cas, les exemples ci-dessus se transformeront en

// 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

Vous pouvez prendre le code votre fonction principale qui fonctionne avec le tableau 2D des doubles, et déplacez-la dans myClass en tant que fonction membre. Non seulement vous n'aurez pas à faire face à la difficulté de passer un pointeur pour ce tableau 2D, mais le code externe à votre classe n'aura plus besoin de connaître les détails de la façon dont votre classe implémente A, puisqu'ils appellent maintenant une fonction dans myClass et laisser faire le travail. Si, par exemple, vous décidez par la suite d'autoriser les dimensions variables de A et que vous choisissez de remplacer le tableau par un vector de vector s, vous n'avez pas besoin de réécrire le code appelant pour que cela fonctionne.

0

Rendre M public au lieu de privé. Puisque vous voulez autoriser l'accès à M via un pointeur, M n'est pas encapsulé de toute façon.

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; 
} 

je, en général, préfèrent R sur A parce que l'ensemble des longueurs sont fixes (A pourrait potentiellement pointer vers un double[10][3] si c'était une exigence) et la référence sera généralement conduire à un code plus clair.