La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Les surcharges d'opérateurs

Présentations similaires


Présentation au sujet: "Les surcharges d'opérateurs"— Transcription de la présentation:

1 Les surcharges d'opérateurs
Ou comment se compliquer un peu la vie pour se la simplifier énormément…

2 Classes et types Une classe joue le rôle d'un type (struct) État + comportement Comportement : méthodes Les types de base aussi ! Types numériques : opérations arithmétiques et numériques + comportements de base : afficher / saisir

3 Classes et types Utiliser la même syntaxe pour un même comportement. Or, comportement = méthode… Et les opérateurs ? En C : mots-clef du langage , ou fonctions En C++ : tout est méthode !

4 Classes et types Un opérateur est une méthode. On peut le surcharger : adaptation à la classe Exemple avec les nombres complexes. //complex.h class Complex { double re, im; public : Complex(double=0.0,double=0.0); ~Complex(); Complex(const Complex &); // pas forcément utile void afficher() const; }

5 Exemple : Complex //complex.cpp #include "complex.h" #include <iostream> using namespace std; Complex::Complex(double r, double i):re(r),im(i) {} Complex::~Complex() {} Complex::complex(const Complex &z) { re = z.re; im = z.im; } void Complex::afficher() const cout << re << "+i" << im << endl; // version naïve

6 Exemple : Complex << est un opérateur, donc une méthode !
// main.cpp #include "complex.h" int main(int argc, char *argv[]) { Complex z(1.0,-3.5); z.afficher(); Au lieu de : cout << z << endl; return 0; } << est un opérateur, donc une méthode ! Ce serait bien plus pratique à utiliser

7 Opérateur << Utilisation générale : Compris comme :
flot << expression; Compris comme : operator<<(flot, expression); Méthode non membre d'une classe Nom de méthode paramètres

8 Opérateur << : implémentation
// complex.h class Complex { … friend ostream& operator<<(ostream&, const Complex &); }; // complex.cpp ostream& operator<<(ostream& os, const Complex &z) os << z.re << "+" << z.im << "i"; return os; } Donc déclarée amie de la classe Méthode non membre de classe Pas de this, un paramètre const car pas modifié Accède à re et im qui sont private

9 Opérateur << : implémentation
// complex.cpp ostream& operator<<(ostream& os, const Complex &z) { os << z.re << "+" << z.im << "i"; return os; } Paramètre os : ostream& : référence vers un flot de sortie cout ou un fichier ! Le flot est modifié par l'écriture des données, il est donc retourné pour être traité de nouveau

10 Opérateur >> // complex.h class Complex { … friend istream& operator>>(istream&, Complex &); }; // complex.cpp istream& operator>>(istream& is, Complex &z) is >> z.re; is >> z.im; return is; } Le paramètre n'est plus const car modifié par la saisie !

11 Opérateurs mathématiques
Sont également surchargeables : + - * / += -= *= /= Exemple avec + : operator+ Méthode membre ou méthode amie ? Méthode membre de classe : class Complex {… Complex operator+(const Complez &); // un seul paramètre ? } Méthode amie Class Complex { friend Complex operator+(const Complex &, const Complex &); Pas de piège : c'est simplement le type de retour de la méthode !

12 Operateur + : méthode membre
// complex.h class Complex {… Complex operator+(const Complez &); // un paramètre ? }; //complex.cpp Complex Complex::operator+(const Complex &z) { Complex resul; resul.re = this->re + z.re; resul.im = im + z.im; return resul; } Oui, car appelé par un objet de type complexe : this est le premier terme Ou return(Complex(re+z.re,im+z.im));

13 Operateur + : méthode membre
// main.cpp #include "complex.h" int main(int argc, char *argv[]) { Complex z1(1,1), z2(4,3), z3; z3 = z1+z2; // ok z3 = z1+z2+z3; // ok return 0; } Inconvénient : le premier terme de + doit être de classe Complex (car méthode membre) Compris comme : z3 = z1.operator+(z2); Compris comme : z3 = z1.operator+(z2.operator+(z3));

14 Operateur + : méthode amie
// complex.h class Complex {… friend Complex operator+(const Complez &, const Complex &); }; //complex.cpp Complex operator+(const Complex &z1, const Complex &z2) { Complex resul; resul.re = z1.re + z2.re; resul.im = z1.im + z2.im; return resul; } Rappel : accède à re et im qui sont private ! Ou return(Complex(z1.re+z2.re,z1.im+z2.im));

15 Operateur + : méthode amie
// main.cpp #include "complex.h" int main(int argc, char *argv[]) { Complex z1(1,1), z2(4,3), z3; z3 = z1+z2; // ok z3 = z1+z2+z3; // ok return 0; } Les 2 termes doivent pouvoir être convertis en Complex. Addition double+Complex ? Compris comme : z3 = operator+(z1,z2); Compris comme : z3 = operator+(z1,operator+(z2,z3));

16 Opérateurs modifiant l'objet
Exemple : opérateur += Doit respecter l'associativité : retour de référence Retour de la valeur de l'objet modifié : c'est *this Prototype : Complex& operator+=(const Complex &); Complex& Complex::operator+=(const Complex& z) { re = re+z.re; // ou re += z.re; im = im+z.im; // ou im += z.im; return *this; }

17 Conversions Constructeurs de conversion
Convertir une valeur d'un type (ou classe) T vers un type (ou classe) D :créer un constructeur de D ayant un argument de type T Application : //complex.h : Class Complex{… Complex(double r); }; //complexe.cpp Complex::Complex(double r):re(r),im(0) {} Assure la conversion double-> Complex

18 Conversions Méthodes de conversion
Convertir un Complex en double (pour calcul de module par exemple) Méthode nommé operator T() où T est le type de destination : operator double(); Complex::operator double() { return sqrt((re*re)+(im*im)); } Sans type de retour (le nom l'indique)

19 Conversions : utilisation
void f(double val) // fonction non membre de classe { cout << val << endl; } int main(int argc, char *argv[]) Complex z(1,1); f(z); // conversion en double 1.414

20 L'opérateur d'affectation =
Similaire au constructeur par recopie : à fournir lorsque la classe contient des attributs de type pointeur // exemple.h class Toto {…}; class Exemple { Toto *var; public : Exemple(…); Exemple(const Exemple &); // par recopie ~Exemple(); Exemple& operator=(const Exemple&); // affectation };

21 L'opérateur d'affectation =
//exemple.cpp Exemple& Exemple::operator=(const Exemple &source) { if (var) delete var; } var = new Toto(*(source.var)); return *this; source Exemple Toto (à recopier) var Toto (recopié) Exemple Toto (avant affectation) this var

22 L'opérateur d'affectation =
Et si &source == this ??? (auto-affectation) Exemple& Exemple::operator=(const Exemple &source) { if (var) delete var; } var = new Toto(*(source.var)); return *this; source Exemple Toto (à recopier) var Exemple Toto (avant affectation) this var

23 L'opérateur d'affectation =
//exemple.cpp Exemple& Exemple::operator=(const Exemple &source) { if (&source != this) if (var) delete var; } var = new Toto(*(source.var)); return *this;

24 L'opérateur [] Indexation : choisir le type de l'index et le type de retour : sécuriser les accès à un tableau class TableauSec { long *valeurs; // plus tard, on mettra ce qu'on veut long taiMax; long taiUtil; public : TableauSec(long=10); TableauSec(const TableauSec&); ~TableauSec(); TableauSec& operator=(const TableauSec&); long& operator[](long); TableauSec& operator+(long); };

25 Digression : opérateur+
Ajouter un élément au tableau en faisant tab = tab+element ! Prototype : TableauSec& operator+(long); // dans tableausec.cpp TableauSec& TableauSec::operator+(long val) { if (taiUtil < taiMax) valeurs[taiUtil++] = val; } return *this; // retour du tableau modifié Message du Ministère du C++ : l'abus de surcharge peut être dangereux pour la santé mentale.

26 L'opérateur [] Prototype : long& operator[](long);
// dans tableausec.cpp long& TableauSec::operator[](long index) { if ((index >=0) && (index < taiutil)) return valeurs[index]; } else // que faire ici ? On verra plus tard !


Télécharger ppt "Les surcharges d'opérateurs"

Présentations similaires


Annonces Google