• Aucun résultat trouvé

Programmation par Objets en C++

N/A
N/A
Protected

Academic year: 2022

Partager "Programmation par Objets en C++"

Copied!
23
0
0

Texte intégral

(1)

Programmation par Objets en C++

Cl ´ement PERNET

L3-MI, UFR IM2AG, Universit ´e Grenoble Alpes

(2)

Plan du cours

Exceptions (5)

(3)

Plan

Exceptions (5) Principe

Les exceptions en C++

Gestion de plusieurs exceptions Propri ´et ´es diverses

(4)

Plan

Exceptions (5) Principe

Les exceptions en C++

Gestion de plusieurs exceptions Propri ´et ´es diverses

(5)

Gestion des exceptions

Situationsexceptionnelles: I Erreur de saisie clavier I Division par 0

I ´echec d’un algorithme probabiliste I acc `es hors d’un intervalle d’indices, ...

Id ´ee 1 :Laisser le programmeur les traiter de fac¸on explicite

I Omissions possibles

I Codes confus et rapidement illisible

I Difficile de traiter le probl `eme autre-part que dans la fonction cr ´eant le probl `eme

I Paradigme des valeurs de retour (9 ou -1) : inapplicable aux constructeurs

(6)

Gestion des exceptions

Situationsexceptionnelles: I Erreur de saisie clavier I Division par 0

I ´echec d’un algorithme probabiliste I acc `es hors d’un intervalle d’indices, ...

Id ´ee 2 : Traitement parexceptions

I Distinction entre le contexte de d ´etection et le contexte du traitement

I S ´eparation du traitement des exception du reste du code : meilleure lisibilit ´e

(7)

Plan

Exceptions (5) Principe

Les exceptions en C++

Gestion de plusieurs exceptions Propri ´et ´es diverses

(8)

Les exceptions en C++

Une exception

I est un objet (et non plus unint),

I est lev ´ee par le mot cl ´ethrow(et non plus parreturn) I est r ´ecup ´er ´ee par un bloctryet un gestionnairecatch

#include <iostream> class DivParZero {}; class Rationnel {

int _num,_den; public:

Rationnel(int n, int d):_num(n),_den(d){ if (!d) throw DivParZero();

} };

int main(){ try{

int n,d;

std::cin>>n>>d; Rationnel r(n,d); }

catch (DivParZero e){

std::cout<<"Denominateur nul, je quitte!"<<std::endl; return 1;

}

return 0; }

(9)

Les exceptions en C++

Une exception

I est un objet (et non plus unint),

I est lev ´ee par le mot cl ´ethrow(et non plus parreturn) I est r ´ecup ´er ´ee par un bloctryet un gestionnairecatch

#include <iostream>

class DivParZero {};

class Rationnel { int _num,_den;

public:

Rationnel(int n, int d):_num(n),_den(d){

if (!d) throw DivParZero();

} };

int main(){

try{

int n,d;

std::cin>>n>>d;

Rationnel r(n,d);

}

catch (DivParZero e){

std::cout<<"Denominateur nul, je quitte!"<<std::endl;

return 1;

}

return 0; }

(10)

D ´eclenchement d’une exception

Nature des exceptions : sans contrainte (contrairement `a Java) I type de base :int, char, etc

I classes : pouvant ˆetre structur ´ees par h ´eritage, v ´ehiculent l’information sur le contexte de lev ´ee.

class DivParZero{};

D ´eclenchement de l’exception : throwsuivi d’une instance d’une classe identifiant l’exception

throw DivParZero();

Sp ´ecification : Les m ´ethodespouvaientsp ´ecifier quelles exceptions sont peuvent ˆetre l ´ev ´ee pendant leur ex ´ecution.

Rationnel (int x, int y) throw (DivParZero) {...}

I d ´epr ´eci ´e enC++11et supprim ´e enC++17

I restenoexcept: sp ´ecifie qu’aucune exception sera lev ´ee

(11)

D ´eclenchement d’une exception

Nature des exceptions : sans contrainte (contrairement `a Java) I type de base :int, char, etc

I classes : pouvant ˆetre structur ´ees par h ´eritage, v ´ehiculent l’information sur le contexte de lev ´ee.

class DivParZero{};

D ´eclenchement de l’exception : throwsuivi d’une instance d’une classe identifiant l’exception

throw DivParZero();

Sp ´ecification : Les m ´ethodespouvaientsp ´ecifier quelles exceptions sont peuvent ˆetre l ´ev ´ee pendant leur ex ´ecution.

Rationnel (int x, int y) throw (DivParZero) {...}

I d ´epr ´eci ´e enC++11et supprim ´e enC++17

I restenoexcept: sp ´ecifie qu’aucune exception sera lev ´ee

(12)

D ´eclenchement d’une exception

Nature des exceptions : sans contrainte (contrairement `a Java) I type de base :int, char, etc

I classes : pouvant ˆetre structur ´ees par h ´eritage, v ´ehiculent l’information sur le contexte de lev ´ee.

class DivParZero{};

D ´eclenchement de l’exception : throwsuivi d’une instance d’une classe identifiant l’exception

throw DivParZero();

Sp ´ecification : Les m ´ethodespouvaientsp ´ecifier quelles exceptions sont peuvent ˆetre l ´ev ´ee pendant leur ex ´ecution.

Rationnel (int x, int y) throw (DivParZero) {...}

I d ´epr ´eci ´e enC++11et supprim ´e enC++17

I restenoexcept: sp ´ecifie qu’aucune exception sera lev ´ee

(13)

D ´eclenchement d’une exception

Nature des exceptions : sans contrainte (contrairement `a Java) I type de base :int, char, etc

I classes : pouvant ˆetre structur ´ees par h ´eritage, v ´ehiculent l’information sur le contexte de lev ´ee.

class DivParZero{};

D ´eclenchement de l’exception : throwsuivi d’une instance d’une classe identifiant l’exception

throw DivParZero();

Sp ´ecification : Les m ´ethodespouvaientsp ´ecifier quelles exceptions sont peuvent ˆetre l ´ev ´ee pendant leur ex ´ecution.

Rationnel (int x, int y) throw (DivParZero) {...}

I d ´epr ´eci ´e enC++11et supprim ´e enC++17

I restenoexcept: sp ´ecifie qu’aucune exception sera lev ´ee

(14)

R ´eception d’une exception

try{

...

}

catch (const DivParZero& e){

... // bloc catch

}

le bloctry: d ´efinit la zone o `u la lev ´ee d’exception est attendue.

le bloccatch: le gestionnaire d’exception

I d ´efinit le comportement lorsque une exception est lev ´ee. I permet de d ´efinir des comportements diff ´erents pour une

m ˆeme exception selon le contexte

I fonctionne comme un passage d’argument `a une fonction I fonctionne comme un block{}et non une fonction :

I acc `es aux variables du contexte englobant I returnsort de la m ´ethode courante Les blocstryetcatchdoivent ˆetre contigus.

(15)

R ´eception d’une exception

try{

...

}

catch (const DivParZero& e){

... // bloc catch

}

le bloctry: d ´efinit la zone o `u la lev ´ee d’exception est attendue.

le bloccatch: le gestionnaire d’exception

I d ´efinit le comportement lorsque une exception est lev ´ee.

I permet de d ´efinir des comportements diff ´erents pour une m ˆeme exception selon le contexte

I fonctionne comme un passage d’argument `a une fonction I fonctionne comme un block{}et non une fonction :

I acc `es aux variables du contexte englobant I returnsort de la m ´ethode courante Les blocstryetcatchdoivent ˆetre contigus.

(16)

Gestion de plusieurs exceptions

Blocscatchsuccessifs :

I parcourus dans l’ordre jusqu’ `a ce que l’exception lev ´ee soit compatible en affectation

I une fois un bloccatchex ´ecut ´e, l’ex ´ecution reprend apr `es le dernier.

#include <iostream>

class DivParZero{};

class RacineDeNegatif{};

void f(int x){

try{

Rationnel(1,x);

throw RacineDeNegatif();

}

catch (const DivParZero& e){std::cerr<<"div par 0, ";}

catch (const RacineDeNegatif& e){

std::cerr<<"SQRT(<0)"<<std::endl; exit(-1);

}

std::cout<<"ok"<<std::endl;

}

int main(){

f(0); // -> div par 0, ok f(1); // -> SQRT(<0)

}

(17)

Plan

Exceptions (5) Principe

Les exceptions en C++

Gestion de plusieurs exceptions Propri ´et ´es diverses

(18)

Gestion de plusieurs exceptions

Quand lister toutes les exceptions devient fastidieux : I utiliser l’h ´eritage et le polymorphisme

I bloccatch(...)pour r ´ecup ´erer toute exception

class ErreurMaths{};

class DivParZero : ErreurMaths{};

class RacineDeNegatif : ErreurMaths{};

class SystInconsistent : ErreurMaths{};

void f(int x){

try{

Rationnel(1,x);

throw RacineDeNegatif();

}

catch (const DivParZero& e){}

catch (const ErreurMaths& e){}

// pour toute autre exception d’ErreurMath, // de RacineDeNegatif ou SystInconsistent catch (...){} // pour toute autre exception

}

(19)

Plan

Exceptions (5) Principe

Les exceptions en C++

Gestion de plusieurs exceptions Propri ´et ´es diverses

(20)

Transmission d’information au gestionnaire

Par l’objet soumis `athrow:

struct Point{

int _x,_y;

Point (int x, int y) {

if ( (x < 0) || (y < 0) ) throw ErrCoord(x,y);

_x = x; _y = y;

} };

struct ErrCoord {

ErrCoord (int a, int o): _abs(a), _ord(o) {}

int _abs, _ord;

};

...

// bloc catch de la methode main catch(const ErrCoord& e) {

std::cout << "Erreur construction du Point ("

<< e._abs << ", " << e._ord << ")" << std::endl;

return -1;

}

(21)

Bonnes pratiques

I On intercepte les exception enconst &: permet I d’ ´eviter une copie inutile

I d’utiliser le polymorphisme et la r ´esolution dynamique I Parfois : re-d ´eclenchement d’une exception : permet

d’effectuer un traitement, sans interrompre la chaˆıne de lev ´ee d’exception.

try{...}

catch(const ErrPoint& e) { ...

throw e;

// ou plus simplement

throw; // l’exception du bloc catch courant est implicite

}

I Exception dans un constructeur : OK

I Exception dans un destructeur : NON ( `a moins qu’elle y soit g ´er ´ee en interne)

(22)

Les exceptions de la librairie standard

La biblioth `eque standard fournit une hi ´erarchie de classe d’exceptions (dans#include <exception>)

class exception{

public:

exception();

virtual ˜exception();

virtual const char* what() const; // chaˆıne d´ecrivant l’

exception

};

Classes d ´eriv ´ees :

class bad_alloc : exception {...}; // lev´ee par new

class bad_cast : exception {...}; // lev´ee par dynamic_cast class bad_typeid : exception {...}; // lev´ee par typeid class runtime_error: exception {...};

class logic_failuer: exception {...}; class overflow_error: runtime_error {...}; class out_of_range : logic_failure {...}; class invalid_argument : logic_failure {...};

(23)

Les exceptions de la librairie standard

La biblioth `eque standard fournit une hi ´erarchie de classe d’exceptions (dans#include <exception>)

class exception{

public:

exception();

virtual ˜exception();

virtual const char* what() const; // chaˆıne d´ecrivant l’

exception

};

Classes d ´eriv ´ees :

class bad_alloc : exception {...}; // lev´ee par new

class bad_cast : exception {...}; // lev´ee par dynamic_cast class bad_typeid : exception {...}; // lev´ee par typeid class runtime_error: exception {...};

class logic_failuer: exception {...};

class overflow_error: runtime_error {...};

class out_of_range : logic_failure {...};

class invalid_argument : logic_failure {...};

Références

Documents relatifs

Point p2=p1 ; // constructeur de recopie : création de l’objet p2 // et son initialisation avec les données de p1.. Attention : il faut différencier entre recopie et

Une classe A utilise une autre classe B si elle déclare en son sein une ou plusieurs entités de la classe B et en appelle les méthodes.. On dit aussi que la classe A est cliente de

On appelle type abstrait de données (TAD) un ensemble d'objets caractérisés par les opérations qui leur sont tous applicables... TYPE ABSTRAIT

Fonction C normale qui jouit du privilège d'avoir accès aux membres privés d'une classe.. ✔ On la déclare friend au sein de

Cette implémentation s'est en fait contenté, avec super.clone(); , de faire appel à la méthode clone() héritée de Object , qui crée un objet de la même classe que l'original

c) Comme l'intensité mesurée est positive, les électrons (qui ont un sens de parcours opposé au sens conventionnel du courant) partent donc de l'armature supérieure pour arriver

- 1 o ) Ecrire une m´ethode d’initialisation (sans argument) qui demande une ´ chaˆıne de moins de quinze caract`eres (repr´esentant la langue) et, pour chaque entier compris entre

Comme dans le cas d’une méthode, si le code est très court, on peut directement mettre le constructeur dans la déclaration de la classe (définition en ligne). Exemple :