Les Classes les structures en C (struct) regroupent des variables : structuration de l'analyse mais...

Post on 04-Apr-2015

107 views 2 download

Transcript of Les Classes les structures en C (struct) regroupent des variables : structuration de l'analyse mais...

Les Classes

les structures en C (struct)

regroupent des variables : structuration de l'analyse

mais

• problèmes de cohérence

• problèmes de sécurité d'accès

• problèmes de syntaxe d'utilisation

limitation des structures

cohérence

exemple : taille utile de tableaustruct s_tablo{

long tab[100];long util;

};

taille gérée "à la main" dans le programme

limitation des structures

or : information a priori en lecture seule

taille mise à jour en fonction des opérations effectuées.

on peut tout de même faire :

struct s_tablo t_tab;

t_tab.util = 142; ne correspond à aucune opération

valeur invalide car > 100

limitation des structures

problème de syntaxe :

opérateurs et fonctions standard non applicables

écrire des fonctions spécifiques à cette structure mais fonctions non distinguables a priori

Sécurisation des accès

dans une classe C++ :

les membres de la classe ont une accessibilité :

public ou private (par défaut)

les struct du C ont tous leurs champs public.

Intégration des fonctions

distinction champ/membre

dans une classe C++ : les fonctions font partie de la classe : fonctions membres

classe : champs+fonctions = membres de la classe

tout membre a une accessibilité

Utilisation des membres

• les membres public peuvent être utilisés dans du code hors de la classe

• les membres private ne peuvent être utilisés que dans du code à l'intérieur de la classe

contrôle de ce qui peut être programmé

Rédiger une classeclass ma_classe{

public : // membres publicprivate : // membres private

};

int main(){

ma_classe var;

// instructions}

exemple avec Dev

Appel de fonction membre

accès à un membre comme pour les struct

. pour accéder à un membre d'une variable de la classe

-> pour accéder à un membre via un pointeur

exemple avec Dev

Appel de fonction membre

avantage : simplification des appels, plus de fonctions spécifiques n'importe où dans le code

fonction associée à l'objet qui l'appelle

référencé dans la fonction : this

Fonctions spéciales

Éviter les variables non initialiséesen C : pas de contrôle

en C++ : fonction spéciale à ce rôle pour les classes

le constructeur

porte le nom de la classe associée

Fonctions spéciales

appelé automatiquement à la définition de la variable.en général, accessibilité public

class x{

public :x() {//code à effectuer}// autres membres public

private : // membres private};

exemple avec Dev

Fonctions spéciales

rôle : initialiser les membres de classe

pas besoin de fonction init() à appeler de manière explicite

possibilité de :• paramètres• paramètres par défaut• surcharge (plusieurs constructeurs)

Fonctions spéciales

appel de constructeur avec paramètres

classe objet(paramètres);

exemple :class x{

public : int j;x(int i){j=i};

};

dans main() : x toto(4);

Fonctions spéciales

un exemple avec un programme

la classe Complexe

avec plusieurs constructeurs

c'est parti !

Membres de type pointeur

création de variable : constructeur

gestion des membres de type : pointeur

retour sur le tableau avec taille utile

constructeur avec paramètre pour taille utile :

réaliser une allocation dynamique

Membres de type pointeurclass tablo{

private : long util;double *valeurs;

public :tablo(long nb) // constructeur{

util=nb;

if (util<=0){

util = 0;valeurs = null;

}else{

valeurs = new double[util];}

}

// autres fonctions membres}

Membres de type pointeurclass tablo{

public :

void afficher(){ for(long cpt=0; cpt < util; cpt++) {

cout << "valeurs[" << cpt << "] = " << valeurs[cpt] << endl; }

return;}

}

le tableau dynamique est toujours bien initialisé (tester le résultat de new)

Membres de type pointeur

libérer l'espace alloué ?

quand ?

de quelle manière ?

lorsque l'objet est détruit

par l'appel automatique à une fonction membre : le destructeur

Destructeur

porte le nom de la classe précédé de ~

• pas de type de retour

• pas d'arguments

• pas de surcharge

Destructeur

exemples :

classe complexe :~complexe(){} // car rien à faire

classe tablo :~tablo(){

if (valeurs != null){

delete[] valeurs;}

}

new/delete

utilisés pour créer des tableaux d'objets

new : alloue de la mémoireappelle le constructeur

delete : appelle le destructeurlibère la mémoire allouée

exemple avec Dev

Copie d'objets

opération fréquente toujours implicite :

passage de paramètres,

création d'un objet à partir d'un autre

classe objet1;

classe objet2(objet1); // OK

classe objet2 = objet1;

il ne s'agit pas d'une affectation !

Copie d'objets

risquée si un membre est un pointeur !

écrire un constructeur par recopie, le rendre explicite

classe(const classe& paramètre);

passage de const & ?

Copie d'objets

évite le partage de contenu

systématique lorsque la classe a un membre de type pointeur.

Rédaction de classe

partie interface

partie implémentation (code)

séparation en .h / .cpp

prototype et définitions de membres

code des fonctions membres

Rédaction de classe

dans le fichier .cpp, le nom de la fonction membre inclue la classe à laquelle elle appartient[type] classe::fonction(paramètres){

code;[return;]

}

:: résolution de portée

exemple avec Dev

Surcharge des opérateurs

force du C++ : modifier la syntaxe

définir les opérateurs standard pour la classe

opérateur = fonction

syntaxe cohérente

<< et >> toujours surchargés (ou presque)

Surcharge des opérateurs

opérateurs surchargeables :

arithmétiques : + - * / ++ -- %

logiques : && || < <= > >= == !=

autres : [] = << >> -> new delete

Surcharge des opérateurs

surcharge des E/S : << et >>

pas des fonctions membres !

pourtant, doivent accéder aux membres private.

déclarées comme fonctions amies

friend

Surcharge des opérateursclass point2d // pour des graphiques en 2D{ private :

double x,y; public :

point2d(double=0.0, double=0.0);~point2d();point2d(const point2d&);

friend ostream& operator<<(ostream &, const point2d&);};

code de la fonction :ostream& operator<<(ostream &os, const point2d &p){

os << "(" << p.x << "," << p.y << ")";return os;

}

Surcharge des opérateursclass point2d // pour des graphiques en 2D{ private :

double x,y; public :

point2d(double=0.0, double=0.0);~point2d();point2d(const point2d&);

friend istream& operator>>(istream &, point2d&);// pas de const point2d& !!!

};

code de la fonction :istream& operator>>(ostream &is, point2d &p){

is >> p.x >> p.y;return is;

}exemple avec Dev

les nombres complexes

redéfinir les opérateurs arithmétiques

les nombres complexes

en faire une classe se comportant comme un type de base

les opérateurs arithmétiques ont un sens pour cette classe

les nombres complexes

2 possibilités

complex operator+(const complex&);

friend complex operator+(const complexe &, const complexe &);

fonction membre

fonction amie

les nombres complexes

différence ?complex z1, z2;

cout << z1+z2;

+ fonction membre :

z1.operator+(z2);

+ fonction amie :operator+(z1,z2);

et l'opérateur << ?

les nombres complexes

En fait :

cout << z1+z2;

operator<<(cout,z1.operator+(z2));

ou

operator<<(cout,operator+(z1,z2));

il n'y a que des appels de fonctions !

les nombres complexes

choix d'une fonction amie

fonction membre : l'opérande de gauche doit être de la classe dont l'operator est membre :pas de conversion possible.

fonction amie : les deux opérandes sont symétriques

les opérateurs surchargés

implémentation d'un opérateur

complex operator+(const complex &z1, const complex &z2){

return complex(z1.re+z2.re,z1.im+z2.im);}

exemple avec Dev

l'opérateur =

presqu'identique au constructeur par recopie

nécessaire lorsque l'on traite des pointeurs

mais bug très vicieux

le cas de l'auto affectation !

l'opérateur =class toto{// du code ici};

class w{ private :

toto *p; // pointe sur un objet de classe toto

public : // constructeurs, destructeur, surcharges classiques

w& operator=(const w& source){

if (values){

delete p;}

p = new toto(*(source.p)); // aie aie aie….

return *this;}

}

l'opérateur =

tester si this est égal à &source !

if (this==&source) return *this;

Objets temporaires

créés dans des expressions, durée de vie très brève

Conclusion

Écriture de classes robustes

• sécurité d'accès

• facilité d'utilisation

• initialisation garantie