slt ma question est tres simple ,comment on fait pour savoir si la fonction qui surcharge un operateur doit etre une methode amie ou pas ?
Merci bcp
slt ma question est tres simple ,comment on fait pour savoir si la fonction qui surcharge un operateur doit etre une methode amie ou pas ?
Merci bcp
Je dirais qu'elle a besoin d'être amie seulement si elle utilise des membres non-publics de la classe...
Je ne sais pas si la question n'était pas plutôt de savoir comment choisir un opérateur membre ou non membre ?
Si c'est bien ça ta question, alors saches qu'il est nécessaire de passer par un opérateur non membre lorsque ton objet se trouve en deuxième opérande d'un opérateur binaire.
Par exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 class Test {}; Test t; int i; // Opérateur membre ok t + i; // Opérateur non membre obligé i + t;
ok merci bcp ,sinon en faisant un exercie j'ai rencontré un truc bizzare voila le codemerci
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 tableau::tableau():nbvaleur(1),valeurs(new int) {} tableau::tableau(int nb):nbvaleur(nb),valeurs(new int[nb]) { for (int i=0;i<nbvaleur;i++) { valeurs[i]=0; } } tableau::~tableau() { delete [] valeurs ; } bool tableau::indice(int ind)const { if (ind>0 && ind<nbvaleur) { return true; } throw("indice hors borne\n"); } int& tableau::operator[](int ind)const { try { indice(ind); } catch(const char* erreur) { cout<<erreur<<endl; } return valeurs[ind]; } int main() { const tableau t(10); // le tableau est declaré comme constant mais je peux //le modifier cout<<t[1]<<endl; t[1]=1; // prq ça fonctionne ? cout<<t[1]<<endl; cin>>t[1];// de meme ici cout<<t[1]; return 0; }
Ca fonctionne car l'opérateur [] est déclaré const mais il renvoie aussi une référence non constante vers un des éléments;
Si tu modifies le retour de l'opérateur [] de int & en int const & cela serait plus logique.
Ca marche parceque ton operateur [] renvoie un int &.
la version correcte prends 2 operateurs [] :
L'un est const et renvoie un const int &, l'autre n'est pas const et autorise la modification de l'int renvoyé.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 const int & tableau::operator[](int ind)const { } int& tableau::operator[](int ind) { }
ok merci bcp .
L'amitié est rarement nécessaire.
Dans le cas des opérateurs mathématiques, pour raisons de symétries, on rend les opérateurs binaires libres, et par commodité dépendant de ceux auto-modifiant (je ne trouve pas de meilleur nom)
->Cas particulier: quand un opérateur lie deux classes différentes comme un vecteur et une matrice. Même en présence d'accesseurs qui vont bien (operateur[]), il est fréquent d'utiliser l'amitié pour raisons d'optimisation. Dans ce cas là, ce n'est pas choquant vu qu'il s'agit de toutes façons de classes très liées.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 struct T { T& operator+=(T const& rhs) { .... // opérateur membre => l'amitié ne veut rien dire pour lui } ... }; T operator+(T const& lhs, T const& rhs) { return T(lhs) += rhs; }
Pour les opérateurs liés aux flux, on peut s'en passer à l'aide de constructeurs d'initialisation (plus un moyen de mettre à jour une tierce donnée de même type (opérateur d'affection, swap, ...)), et des accesseurs qui vont bien.
Ceci dit, il est fréquent de voir ces opérateurs en amis (avec présence d'un constructeur par défaut).
(Plus un petit swap qui va bien.)
Ce pas faux. En effet. J'avais complètement zappé cette famille de cas.
Et pour la surcharge des opérateurs d'indirection de flux dans une classe template, vous feriez comment?
Par exemple, une classe Matrix qui implémente une matrice 2D template du style:
. Quelle serait la meilleure solution?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 template <typename T> class Matrix { // constructeurs, opérateurs, ... private: std::vector<T> _matrix; };
Ok merci.
Du coup, je me demande ce que vous pensez de cette solution:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 #include <vector> #include <ostream> #include <algorithm> template <typename T> class Matrix2D { public: Matrix2D(unsigned int nbCol = 4, unsigned int nbRow = 4) : _nbCol(nbCol) , _nbRow(nbRow) , _matrix( std::vector<T>(nbCol*nbRow) ) {} ~Matrix2D(){} void Fill(T elt) { std::fill(_matrix.begin(), _matrix.end(), elt); } struct DumpOne { DumpOne(std::ostream & stream, unsigned int nbCol) : _count(0) , _stream(stream) , _nbCol(nbCol) {} void operator () (T& t) { _stream << t; if (++_count==_nbCol) { _stream << std::endl; _count = 0; } } private: unsigned int _count; std::ostream & _stream; unsigned int _nbCol; }; void Dump(std::ostream & stream) { std::for_each( _matrix.begin(), _matrix.end(), DumpOne(stream, _nbCol) ); stream << std::endl; } private: unsigned int _nbCol, _nbRow; std::vector<T> _matrix; }; template <typename T> std::ostream & operator << (std::ostream & stream, Matrix2D<T> & matrix) { matrix.Dump(stream); return stream; }
for_each est autorise a copier comme il veut l'objet fonction qui lui est passe. Donc le modifier comme tu le fais n'est pas sage -- ca peut marcher avec une implementation et pas avec un autre.
Ha. Que devrais-je donc faire pour y remédier? Implémenter le constructeur par copie du foncteur DumpOne ?
Donner a DumpOne une semantique de reference. Le texte de la future norme suggere pour le moment l'utilisation de reference_wrapper<T>, mais je doute que ce soit une solution pour toi pour le moment.
Ok d'ac. M'enfin, c'est par curiosité que je demandais ça, je n'ai pas besoin de ça pour l'instant.
Tiens, en parlant de la nouvelle norme, tu as vu qu'il y a un meeting prévu à sofia antipolis du 8 au 14 juin 2008? ( cf le blog d'H.S.)
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager