Bien ceci constitue mon premier post sur ce forum qui m'a souvent dépanner dans mes déboires avec la programmation (je ne suis pas informaticien de formation même si je programme assez souvent).
Je me suis mis au C++ pour différentes raisons et je me retrouve confronter à un problème de surdéfinition d'opérateur. L'exemple typique est celui de l'addition (un operateur binaire donc). Voila un petit code simple pour fixer le cadre :
Ce code n'a pour but que l'exemple, en fait je m'en suis servi pour comprendre le fonctionnement de la surdéfinition d'un opérateur binaire avec une fonction non membre sans utilisation de déclaration d'amitié (friend).
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 template <class T> class Mes_complexe { private : T part_rl_; T part_im_; public : Mes_complexe(T x=0.0,T y=0.0) {part_rl_=x; part_im_=y;} T part_rl() const {return part_rl_;} T part_im() const {return part_im_;} }; template <class T> class Mes_reel : public Mes_complexe<T> { public : Mes_reel(T x=0.0) : Mes_complexe<T>(x) {}; }; // FONCTION NON MEMBRE. template <class T> Mes_complexe<T> operator+(const Mes_complexe<T>& z1, const Mes_complexe<T>& z2) { cout << "Entree dans l operation d addition complexe + complexe.\n"; return Mes_complexe<T>(z1.part_rl()+z2.part_rl(), z1.part_im()+z2.part_im()); } template <class T> Mes_reel<T> operator+(const Mes_reel<T>& r1,const Mes_reel<T>& r2) { cout << "Entree dans l operation d addition reel + reel.\n"; return Mes_reel<T>( r1.Mes_complexe<T>::part_rl()+r2.Mes_complexe<T>::part_rl() ); } template <class T> Mes_complexe<T> operator+(const Mes_complexe<T>& z1,const Mes_reel<T>& r1) { cout << "Entree dans l operation d addition complexe + reel.\n"; return Mes_complexe<T>( r1.Mes_complexe<T>::part_rl()+z1.part_rl(), z1.part_im() ); }
Voilà le problème, tous ici s'accorderont sur le fait que l addition est commutative. J'attire donc votre attention sur la dernière surdéfinition. De ce que j'ai pu lire sur les forums cette dernière fonction permet de créer cette commutativité de façon implicite. Ce qui est vrai dans ce cas.
Si j'ajoute ce main :
Mon problème est le suivant, je pensez que le calcul de Z3 appelez l opération somme complexe reel. Mais en fait pas du tout, ca appelle complexe complexe (suite a une conversion implicite je suppose).
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 main() { Mes_complexe<double> Z=Mes_complexe<double>(1.2,1.8); cout << "Affichage de Z : (" <<Z.part_rl()<<","<<Z.part_im()<<").\n"; Mes_reel<double> R=Mes_reel<double>(1.1); cout << "Affichage de R : (" <<R.Mes_complexe<double>::part_rl()<<").\n"; Mes_complexe<double> Z1, Z2, Z3; Mes_reel<double> R1; Z1=Z+Z; cout << "Affichage de Z1 : (" <<Z1.part_rl()<<","<<Z1.part_im()<<").\n"; R1=R+R; cout << "Affichage de R1 : (" <<R1.Mes_complexe<double>::part_rl()<<").\n"; Z2=Z+R; cout << "Affichage de Z2 : (" <<Z2.part_rl()<<","<<Z2.part_im()<<").\n"; Z3=R+Z; cout << "Affichage de Z3 : (" <<Z3.part_rl()<<","<<Z3.part_im()<<").\n"; }
Pourquoi est ce un problème, certains se poseront peut être la question. En fait ca c est un script de manipulation pour comprendre. J'ai appliquer cette "recette" à un algorithme de somme de Matrices. Sauf qu'il y a plein de type de matrice et toutes utilise un codage particulier de l'accès au donnée. Par exemple, disons qu'on ai une classe MatFull qui gère des matrices générale et MatSym (hérité de MatFull) pour les matrices symétriques. Le but d'avoir Matsym est de ne pas stocker tout les éléments puisque la connaissance des éléments supra diagonaux suffit (diagonale comprise). L'opérateur () est surdéfini pour chacun des types.
Sauf que s'il me fait une conversion implicite de MatSym en MatFull bah ca va planter car l'opérateur () ne sera pas correctement pris en compte (une instance de MatFull représentant une matrice nXn aura n*n éléments stockés soit le nombre d'élément de la matrice et une instance de MatSym représentant une matrice nXn symétrique n'aura que (1/2)*n*(n-1) éléments stockés !!!)
Y a il une façon de procéder dans ce cas là autre que redéfinir tout les types d' addition ; pour revenir au code donné en exemple sur les complexes et les reels ce la donnerai 4 redéfinitions :
_ complexe complexe
_ reel reel
_ complexe reel
_ reel complexe
J'ai un panel de solution mais je suis pas sur ou je n'aime pas pour certaine raison :
_ utilisation des relation d'amitié mais je n'aime pas car j'ai peur de pas pouvoir localiser dans un seul code toutes mes surdefinitions d'addition (l'intérêt c'est de pouvoir travailler indépendamment sur les différentes opérations en ouvrant un seul fichier et ainsi ne jamais oublier de faire les changement requis par un changement de code ultérieur),
_ tous redéfinir comme indiqué plus haut mais là ca fait beaucoup de travail (j'ai plein de type de matrice à utiliser),
_ une surdéfinition intelligente de l'opération de conversion implicite mais la je suis pas sur d'être assez intelligent
Laquelle de ces solutions me conseilleriez vous ? Ou y a t il une autre solution ?
Et dans le cas ou je ne fait pas de surdéfinition de la conversion de type entre mes matrices, ne devrais je pas interdire les conversions implicites de types (je crois que c'est possible mais bon je programme en C++ depuis 2 mois alors je ne maîtrise pas toutes les subtilités).
Bon en espérant que je n'ai pas dit trop de bétise et que je soit clair, il me reste à vous remercier par avance pour l'aide que vous allez m'apporter.![]()
Partager