pointeur de tableau 2D d'entiers... - C++ - Programmation
Marsh Posté le 17-03-2012 à 16:39:13
Un tableau C et un pointeur sont deux choses différentes : int[] et int* sont différents, int[][] et int** sont différents aussi. Quand tu écris return terrain; tu ne dois pas t'attendre à une conversion magique entre ton int terrain[12][12] et ton type de retour int**.
Je vais tenter de dresser un portrait de la situation mais tu vas vite voir que C++ est un langage (très complexe) qui n'aime pas trop les tableaux C, qui sont du coup difficiles à manipuler surtout quand ils ont plusieurs dimensions.
De base C++ "dégrade" le type tableau (à une dimension) qu'on lui passe pour en faire un pointeur (ce comportement vient du C).
On peut donc écrire ce genre de chose :
Code :
|
Note que je suis censé retourner un int* et que visiblement mon return array; ne pose pas de problème. C'est pour ça que je parle de dégradation, en fait c'est une autre écriture pour :
Code :
|
mais ce n'est pas un "vrai" passage de tableau en argument qu'on fait là si je puis dire. D'ailleurs si on veut passer un tableau d'int à 2 dimensions en paramètre, on ne peut pas écrire :
Code :
|
(le message d'erreur nous indique qu'une chose comme "void foobar(int array[][37]) { ... }" marcherait soit dit en passant).
De même si on veut retourner un tableau de ce genre, on ne peut pas écrire des trucs du genre :
Code :
|
Comment on fait alors ? Ben c'est compliqué
C'est pour ça que la plupart du temps :
Un exemple de méthode qui bosse vraiment avec un tableau de taille 5 (et uniquement 5), sans dégrader son type en pointeur :
Code :
|
Je ne pense pas que ce genre de choses soit une bonne idée (syntaxe complexe, taille fixée, etc).
Dans la version la plus récente de C++ on peut faire la même chose avec une syntaxe moins cryptique, en utilisant des templates :
Code :
|
Mon conseil : fait toi une classe Terrain, qui n'utilise qu'en interne des pointeurs genre int** pour manipuler ton int[][]. Dans le reste de ton code après tu utilises cet objet Terrain, mais pas un int**, c'est trop casse-gueule
Marsh Posté le 17-03-2012 à 18:30:41
Pourquoi tu fais plutôt un accesseur sur le tableau ?
genre :
Code :
|
Marsh Posté le 17-03-2012 à 23:54:55
@Terminator : Nan en fait il me faut vraiment la valeur de tout le tableau pour pouvoir le manipuler "une couche au dessus".
@Mathieux : Merci pour ce cours détaillé Je cerne mieux le problème maintenant, en fait comme que je le dis à Terminator, je voudrais utiliser ce tableau "une couche au dessus" dans la fonction qui utilise ma class Map. (Je suis donc obligé de faire mes magouilles sur ces deux étages)
En suivant ton idée, mettons que je déclare dans ma class (en private) mon tableau comme un int **, je fais ensuite une fonction qui retourne simplement tableau (int**).
J'ai deux questions :
- Comment j'initialise mon tableau ? (un malloc est nécessaire non ?)
- Comment j'appelle ma fonction RetourneTableau une couche au dessus? (simplement avec un maCarte.RetourneTableau() ?)
Marsh Posté le 18-03-2012 à 08:26:55
ne pas oublier boost::array (ou std::array) qui permet de manipuler de stableaux C ave cune semantique de valeur correct.
Marsh Posté le 18-03-2012 à 10:57:24
@Mathieux je retire ma question j'ai trouvé un tuto très bien à ce sujet. http://h-deb.clg.qc.ca/Sujets/Dive [...] ux-2D.html Le problème c'est que maintenant j'ai une belle seg fault PROBLEME RESOLU je n'avais juste pas compris le principe du destructeur en fait, je ne pensais pas qu'il s'appliquait directement après le constructeur.
Voila mon constructeur et mon destructeur (tableau de type int**) :
Code :
|
Et ma fonction qui affiche mon terrain en utilisant le tableau d'entier, c'est la que ca seg fault)
Code :
|
Lorque j'appelle maCarte.afficherTerrain(tile,ecran,10,10) ca seg fault ...
Marsh Posté le 18-03-2012 à 13:47:53
T'as pas initialisé les valeurs du tableau, je me trompe ?
Marsh Posté le 18-03-2012 à 16:25:57
Si si, dans mon constructeur.
Mais mon problème est résolu, j'ai juste laissé mon code au cas ou quelqu'un ai le même problème que moi tombe sur cette page.
Mon problème venait en fait de mon destructeur. Je l'ai supprimé et je l'ai remplacé par une fonction "libererTerrain" que j'appelle à la fin de mon programme.
Marsh Posté le 18-03-2012 à 22:48:28
Ton destructeur est appelé lorsque ton instance est supprimée, tu dois mal manipuler une instance quelque part alors
Marsh Posté le 18-03-2012 à 23:02:59
Citation : le destructeur d'un objet créé de façon statique est appelé de façon implicite dès que le programme quitte la portée dans lequel l'objet existe |
Mon destructeur se déclenchait quand je ne le souhaitais pas apparemment. Je l'ai simplement supprimé et remplacé par une fonction libererTableau.
Marsh Posté le 19-03-2012 à 07:49:18
beuted a écrit :
|
Les destructeurs ne se déclenchent pas de manière aléatoire Utilise ton debugger pour mettre un point d'arrêt dans le destructeur et une fois dedans regarde la pile d'appel, pour comprendre d'où ça part. Comme dit Terminapor c'est une erreur de manipulation.
Marsh Posté le 16-03-2012 à 21:10:52
Bonjour, (je créé un nouveau topic pour pas encombrer le précédent)
J'ai un souci avec un passage de fonction en paramètre j'ai beau retourner le problème dans tout les sens ça veut pas compiler...
J'ai un fichier Map.h dans lequel je créé une class avec en private : (ligne 30)
Et en public la fonction qui renvoi ce tableau :
Avec comme code dans le Map.cpp
Ma fonction utilisant cette class comporte #include "Map" et après avoir créé un objet maCarte de type Map demande :
L'erreur que renvoi le compilateur :
map.cpp:30:10: error: cannot convert ‘int (*)[12]’ to ‘int**’ in return
make: *** [map.o] Erreur 1
J'ai beau changer int** en int[12]* il me lève une autre erreur, et ainsi de suite
Merci d'avance.