2010-08-12 5 views
4

J'apprends C++ et ne peut pas obtenir ma tête autour de ce problème:Modification d'un cours par un membre iterator

J'ai une simple classe A

class A { 
private: 
    int ival; 
    float fval; 

public: 
    A(int i = 0, float f = 0.0) : ival(i), fval(f) { } 
    ~A(){ } 
    void show() const { 
     cout << ival << " : " << fval << "\n"; 
    } 
    void setVal(int i) { 
     ival = i; 
    } 

    //const getters for both ival and fval 

    //used for the default "lesser" 
    friend bool operator<(const A& val1, const A& val2) { 
     return val1.ival < val2.ival ? true : false;; 
    } 
} 

Puis j'ai une set<A> myset régulière est rempli avec insert(A(2, 2.2)); dans une boucle.

Itère pour obtenir toutes les valeurs ne sont pas un problème, mais je veux modifier la valeur dans cette itération:

for(set<A>::iterator iter = set3.begin(); iter != set3.end(); iter++) { 
    iter->setVal(1); 
} 

Je suppose que cela devrait être faisable, comme vous le feriez en Java dans un foreach boucle. Lors de la compilation, je reçois error: passing ‘const A’ as ‘this’ argument of ‘void A::setVal(int)’ discards qualifiers. En regardant les sources de l'ensemble STL, je vois que begin() est seulement disponible en tant que méthode const et je pense que cela pourrait être le problème. Messing autour de const sur la méthode setVal() a toujours eu la même erreur et n'aurait pas beaucoup de sens puisque je veux modifier la valeur de A.

Est-ce la mauvaise approche de changer un tas de valeurs de A avec une boucle?

+0

+1 car il semble vraiment que vous cherchez d'abord par vous-même, et ce qui est toujours une bonne chose quand vous apprenez quelque chose de nouveau. – ereOn

+0

Notez que 'val1.ival

+0

@Pedro: merci, maintenant que vous le dites, c'est évident, mais je ne pouvais pas le voir moi-même. – DrColossos

Répondre

5

Le jeu STL ne vous permet pas de modifier les valeurs qu'il stocke. Il le fait en retournant une copie de l'objet à travers l'itérateur (pas le vrai dans l'ensemble).

La raison pour laquelle cela est fait parce qu'il utilise < pour commander l'ensemble et il ne veut pas refaire l'arbre entier chaque fois que vous déréférencer l'itérateur, ce qu'il devrait faire, car il ne sait pas si vous avez changé quelque chose qui change la commande.

Si vous devez mettre à jour l'ensemble <>, supprimez l'ancienne valeur et ajoutez-en une nouvelle.

EDIT: viens de vérifier la source de SGI STL et il dit ceci:

typedef typename _Rep_type::const_iterator iterator; 

Ainsi, un ensemble :: iterator est juste un ensemble :: const_iterator

+0

Cela signifie-t-il que j'ai juste eu de la malchance en essayant avec un ensemble et non avec un autre conteneur? Est-ce que cela fonctionnerait avec un vecteur ou une liste ou ...? – DrColossos

+0

Oui, cela fonctionne avec un 'std :: vector'. –

+1

Vous vouliez dire un const et non une copie. S'il s'agissait d'une copie, il n'aurait pas été const – Scharron

1

De this page, il semble que begin() existe aussi bien qu'une méthode non-const.

Votre ensemble est peut-être passé dans la méthode en tant que référence const?

EDIT

La page référencée est erronée. Comme l'indique Scharron, il n'existe pas de méthode non-const begin() (ou end() pour les matières commandées).

J'informerai le site de leur erreur (ce n'est pas la première qu'ils ont fait;))

+0
+0

Connaissez moi cette page, super ressource! Buf si la définition dans la source est dite const, d'où vient le non-const 'begin()'? – DrColossos

+0

C'est une erreur. L'itérateur et le const_iterator sont du même type sur les conteneurs ordonnés (n'ayant ainsi qu'une seule méthode 'begin() const' et' end() const) – Scharron