2010-04-26 6 views
8

Je dispose d'un fichier d'en-tête de classe appelée Grid.h qui contient les éléments suivants 2 objet de données privées:C++ vecteur de vecteurs

vector<int> column; 
vector<vector<int>> row; 

Et une méthode publique dont le prototype en Grid.h est tel:

int getElement (unsigned int& col, unsigned int& row); 

la définition de la fonction mentionnée ci-dessus est défini comme tel dans Grid.cpp:

int getElement (unsigned int& col, unsigned int& row) 
{ 
    return row[row][col] ; 
} 

Quand je lance le programme, je reçois ce erreur:

error C2109: subscript requires array or pointer type 

Qu'est-ce qui ne va pas?

+3

Quel est le motif vous prenez ces paramètres par référence? Si quelque chose, ils devraient être une référence constante, mais généralement les types fondamentaux ne devraient pas être transmis par référence, sauf si vous en avez besoin. Aussi, pourquoi avoir deux vecteurs? le vecteur à l'intérieur d'un vecteur est à la fois, votre vecteur 'column' est juste autre chose. – GManNickG

Répondre

17

Sur la ligne return row[row][col];, la première row correspond au int&, et non la vector. La variable déclarée dans la portée interne observe la variable dans la portée externe, de sorte que le compilateur essaie d'indexer un int plutôt qu'un vector, ce qu'il ne peut évidemment pas faire.

Vous devez corriger vos noms de variable afin qu'ils ne soient pas en conflit.

EDIT: En outre, alors que l'erreur que vous obtenez indique que le compilateur est de trouver la variable row mal, comme A. Levy souligne, vous avez également un problème avec la déclaration de votre vector, donc même Si vous corrigez les noms des variables, si vous avez effectivement déclaré le vector comme indiqué ici, il ne sera pas compilé. Les modèles imbriqués ont besoin d'espaces entre les symboles >, sinon le compilateur lira >> comme opérateur de décalage vers la droite plutôt que comme partie d'une déclaration de modèle. Il doit être

std::vector<std::vector<int> > row; 

ou

std::vector< std::vector<int> > row; 

En outre, comme vous faites ceci dans un fichier d'en-tête, vous allez avoir besoin de virer de bord l'étiquette std:: sur le devant de quoi que ce soit de l'espace de noms std - tel que vector. Si c'était dans un fichier cpp, alors vous pourriez utiliser using namespace std; mais ce serait très mauvais à faire dans un fichier d'en-tête (car cela polluerait l'espace de noms global). Sans la balise std:: ou l'instruction using, le compilateur ne reconnaîtra pas vector.

+0

si je change le nom des vecteurs en horizontal et vertical, je reçois des erreurs d'identificateur non déclarées pour chacun d'eux – xbonez

+0

Sinon, vous pouvez simplement faire "this-> row [row] [col]" et cela devrait fonctionner. –

8

Ceci n'est probablement pas le problème d'index, mais vous avez également besoin d'un espace entre les chevrons imbriqués dans votre déclaration de type vecteur de vecteurs. Les compilateurs C++ ont du mal à faire la différence entre les types de modèles imbriqués et l'opérateur de décalage de bits correct.

Exemple:

vector<vector<int> > vec2d;  // Good. 

vector<vector<int>> anotherVec2d; // Bad! 

vector< vector<int> > yetAgain;  // Best IMHO. 
            // Keeps the white space balanced. 
+9

@KevenK, un espace entre les deux symboles empêche le compilateur de les traiter comme un seul opérateur. Je voudrais pouvoir rétrograder votre commentaire. –

+3

L'espace est très important dans ce cas. L'analyseur utilise le maximum de munch pour analyser, donc il saisit le plus grand jeton possible. Cela signifie que dans 'le vecteur >' il analysera '>>' comme un opérateur de décalage plutôt que comme une partie d'une déclaration de modèle. Vous avez besoin de l'espace supplémentaire pour indiquer au compilateur que vous déclarez un modèle plutôt qu'une expression avec un opérateur de décalage. –

+3

Cela a été modifié maintenant. Si vous utilisez un compilateur en cours, vous pouvez probablement écrire "vector >" et obtenir ce que vous attendez. Pas encore standard mais VS2010, g ++, et presque certainement d'autres le supportent maintenant. –

1

Il me semble (bien que vous devrez peut-être vérifier sur votre propre, je ne me sens pas envie d'écrire une application de test) que le problème vient du fait que Votre paramètre contient un row nommé et votre classe a une variable interne row et il y a un conflit de nommage.

Vous devrez peut-être qualifier la ligne que vous utilisez.Considérez:

return Grid::row[row][col]; 
+0

Ou retourner this-> row [row] [col] – a1ex07

+0

J'ai renommé ligne et colonne dans le privé: section horizontale et verticale. Je reçois maintenant l'erreur 'horizontal: identificateur non déclaré' et 'vertical: identificateur non déclaré' – xbonez

+0

@xbonez: Pourquoi avez-vous deux vecteurs? Je pensais que tu voulais un vecteur de vecteurs? (Donner un vecteur 2D.) – GManNickG

4

Je pense que vous voulez quelque chose comme ça ... (même si je ne peux pas imaginer pourquoi :-))

#include <vector> 
#include <iostream> 

using namespace std; 

typedef vector<int> row; 
typedef vector<row> matrix; 

matrix mat(2,2); 

int getElement (unsigned int ri, unsigned int ci) 
{ 
    return mat[ri][ci] ; 
} 

int main() { 

    mat[1][0] = 1234; 
    cout << getElement(1,0) << endl; 

    return 0; 
} 
+0

aahhh !! oui, cela semble beaucoup mieux faire. Je n'y ai pas pensé. De cette façon, je n'ai pas besoin d'imbriquer des vecteurs. Merci beaucoup. Je vais l'utiliser de cette façon. – xbonez

+0

Cette réponse est toujours l'imbrication de vecteurs, mais seulement sous un alias typedef de style C qui n'est pas compatible avec les templates ... –

3

C'est ce que vous avez besoin:

return Grid::row[row][col];