le truc, c'est que je comprend pas quoi retourner dans le cas où
l'exception est lancée
le truc, c'est que je comprend pas quoi retourner dans le cas où
l'exception est lancée
le truc, c'est que je comprend pas quoi retourner dans le cas où
l'exception est lancée
salut,
dans le cas où l'utilisateur veut accéder a une case d'un tableau nxm
et que la case demandée dépasse les dimensions du tableau, j'aimerai
lancer une exception...
le truc, c'est que je comprend pas quoi retourner dans le cas où
l'exception est lancée, exemple :
salut,
dans le cas où l'utilisateur veut accéder a une case d'un tableau nxm
et que la case demandée dépasse les dimensions du tableau, j'aimerai
lancer une exception...
le truc, c'est que je comprend pas quoi retourner dans le cas où
l'exception est lancée, exemple :
salut,
dans le cas où l'utilisateur veut accéder a une case d'un tableau nxm
et que la case demandée dépasse les dimensions du tableau, j'aimerai
lancer une exception...
le truc, c'est que je comprend pas quoi retourner dans le cas où
l'exception est lancée, exemple :
Rien du tout. Quand ton opérateur lance l'exception, il quitte la fonction,
c'est à l'utilisateur de ton objet de prévoir ce qu'il faut s'il veut
traiter ton exception. S'il ne fait rien, c'est l'arret du programme en
erreur...
Personnellement, j'ai une classe de base dont dérive toutes mes exceptions,
j'encapsule donc tout le code du main dans un try/catch sur cette classe de
base. Dans le catch je donne toute les informations relative à l'erreur et
je quitte le programme.
C'est plus un problème de design à mon avis, voici ce que j'aurais écrit:
class Erreur : public std::exception {...}; // classe de base des
exceptions
class MatriceError : public Erreur {...};
class MatriceOutOfRange : public MatriceError {...};
class MatriceAutreErreur : public MatriceError {...};
class AutreObjetErreur : public Erreur {...};
Définir une bonne hierarchie de classe, permet à l'utilisateur du programme
de ne traiter que les exceptions qu'il sait traiter et qui ne doivent pas
provoquer l'arrêt du programme et laisser les autres être traitées par le
catch de la boucle principale, s'il y en a un.
double& Matrice::operator()(unsigned int i, unsigned int j)
{
if ( i> n || j > m) throw MatriceOutOfRange();
return lignes[i][j];
}
// main
try
{
...
Matrice mat(3,3);
mat(5, 2); // tu peux ici mettre un try/catch sur MatriceOutOfRange si
cette erreur ne doit pas provoquer l'arrêt du programme...
...
}
catch(Erreur& e)
{
... traitement de l'exception
fin du programme
}
Rien du tout. Quand ton opérateur lance l'exception, il quitte la fonction,
c'est à l'utilisateur de ton objet de prévoir ce qu'il faut s'il veut
traiter ton exception. S'il ne fait rien, c'est l'arret du programme en
erreur...
Personnellement, j'ai une classe de base dont dérive toutes mes exceptions,
j'encapsule donc tout le code du main dans un try/catch sur cette classe de
base. Dans le catch je donne toute les informations relative à l'erreur et
je quitte le programme.
C'est plus un problème de design à mon avis, voici ce que j'aurais écrit:
class Erreur : public std::exception {...}; // classe de base des
exceptions
class MatriceError : public Erreur {...};
class MatriceOutOfRange : public MatriceError {...};
class MatriceAutreErreur : public MatriceError {...};
class AutreObjetErreur : public Erreur {...};
Définir une bonne hierarchie de classe, permet à l'utilisateur du programme
de ne traiter que les exceptions qu'il sait traiter et qui ne doivent pas
provoquer l'arrêt du programme et laisser les autres être traitées par le
catch de la boucle principale, s'il y en a un.
double& Matrice::operator()(unsigned int i, unsigned int j)
{
if ( i> n || j > m) throw MatriceOutOfRange();
return lignes[i][j];
}
// main
try
{
...
Matrice mat(3,3);
mat(5, 2); // tu peux ici mettre un try/catch sur MatriceOutOfRange si
cette erreur ne doit pas provoquer l'arrêt du programme...
...
}
catch(Erreur& e)
{
... traitement de l'exception
fin du programme
}
Rien du tout. Quand ton opérateur lance l'exception, il quitte la fonction,
c'est à l'utilisateur de ton objet de prévoir ce qu'il faut s'il veut
traiter ton exception. S'il ne fait rien, c'est l'arret du programme en
erreur...
Personnellement, j'ai une classe de base dont dérive toutes mes exceptions,
j'encapsule donc tout le code du main dans un try/catch sur cette classe de
base. Dans le catch je donne toute les informations relative à l'erreur et
je quitte le programme.
C'est plus un problème de design à mon avis, voici ce que j'aurais écrit:
class Erreur : public std::exception {...}; // classe de base des
exceptions
class MatriceError : public Erreur {...};
class MatriceOutOfRange : public MatriceError {...};
class MatriceAutreErreur : public MatriceError {...};
class AutreObjetErreur : public Erreur {...};
Définir une bonne hierarchie de classe, permet à l'utilisateur du programme
de ne traiter que les exceptions qu'il sait traiter et qui ne doivent pas
provoquer l'arrêt du programme et laisser les autres être traitées par le
catch de la boucle principale, s'il y en a un.
double& Matrice::operator()(unsigned int i, unsigned int j)
{
if ( i> n || j > m) throw MatriceOutOfRange();
return lignes[i][j];
}
// main
try
{
...
Matrice mat(3,3);
mat(5, 2); // tu peux ici mettre un try/catch sur MatriceOutOfRange si
cette erreur ne doit pas provoquer l'arrêt du programme...
...
}
catch(Erreur& e)
{
... traitement de l'exception
fin du programme
}
ok merci, j'ai fait ce genre de pratique à peu près :
class Erreur
{
private:
int c;
string exp;
public:
static const int ncarre = 0,
multiplication = 1,
notinmat = 2,
dbzero = 3;
Erreur();
Erreur(Erreur &s);
Erreur(int a);
int cause() const;
string explic() const ;
};
Erreur::Erreur(int a)
:c(a)
{
switch(a)
{
case ncarre:
exp = "matrice non carre, operation impossible";
break;
case multiplication:
exp = "erreur de dimension, operation impossible";
break;
case notinmat:
exp = "erreur de taille, operation impossible";
break;
case dbzero:
exp = "division par 0, operation impossible";
break;
default:
exp= "erreur inconnue";
}
}
etc...
et dans une fonction par exemple je fais :
Matrice &
Matrice::operator/=(const double nb)
{
if(nb)
{
for(unsigned int i=0; i<n; i++)
for(unsigned int j=0; j<n; j++)
lignes[i][j]/=nb;
}
else
{
Erreur a(Erreur::dbzero);
throw(a);
}
return *this;
}
ok merci, j'ai fait ce genre de pratique à peu près :
class Erreur
{
private:
int c;
string exp;
public:
static const int ncarre = 0,
multiplication = 1,
notinmat = 2,
dbzero = 3;
Erreur();
Erreur(Erreur &s);
Erreur(int a);
int cause() const;
string explic() const ;
};
Erreur::Erreur(int a)
:c(a)
{
switch(a)
{
case ncarre:
exp = "matrice non carre, operation impossible";
break;
case multiplication:
exp = "erreur de dimension, operation impossible";
break;
case notinmat:
exp = "erreur de taille, operation impossible";
break;
case dbzero:
exp = "division par 0, operation impossible";
break;
default:
exp= "erreur inconnue";
}
}
etc...
et dans une fonction par exemple je fais :
Matrice &
Matrice::operator/=(const double nb)
{
if(nb)
{
for(unsigned int i=0; i<n; i++)
for(unsigned int j=0; j<n; j++)
lignes[i][j]/=nb;
}
else
{
Erreur a(Erreur::dbzero);
throw(a);
}
return *this;
}
ok merci, j'ai fait ce genre de pratique à peu près :
class Erreur
{
private:
int c;
string exp;
public:
static const int ncarre = 0,
multiplication = 1,
notinmat = 2,
dbzero = 3;
Erreur();
Erreur(Erreur &s);
Erreur(int a);
int cause() const;
string explic() const ;
};
Erreur::Erreur(int a)
:c(a)
{
switch(a)
{
case ncarre:
exp = "matrice non carre, operation impossible";
break;
case multiplication:
exp = "erreur de dimension, operation impossible";
break;
case notinmat:
exp = "erreur de taille, operation impossible";
break;
case dbzero:
exp = "division par 0, operation impossible";
break;
default:
exp= "erreur inconnue";
}
}
etc...
et dans une fonction par exemple je fais :
Matrice &
Matrice::operator/=(const double nb)
{
if(nb)
{
for(unsigned int i=0; i<n; i++)
for(unsigned int j=0; j<n; j++)
lignes[i][j]/=nb;
}
else
{
Erreur a(Erreur::dbzero);
throw(a);
}
return *this;
}
Quelques remarques d'implémentation. Tu pourras trouver des détails
intéressants à ce sujet là :
http://www.boost.org/more/error_handling.html
Il est souvent pratique de faire dériver ses exceptions de std::exception ou
d'une de ses sous-classes. Ca facilite grandement la gestion des erreurs
dans le cas où on n'a pas besoin d'une grande finesse.
{
private:
int c;
string exp;
Aïe, aïe, aïe. C'est bien de vouloir formater les messages d'erreur avec des
std::string. Le problème c'est que la construction de la chaîne peut lever
une exception, et que ça devient assez problèmatique dans un contexte de
gestion d'exception. Si tu as vraiment besoin d'un message, ou bien
restreint toi à un buffer statique ou bien alloue le à la main en gèrant
correctement les erreurs potentielles. Dans ton cas, "exp" n'est pas
vraiment utile : elle contient la description de l'erreur codée dans "c".
Or
"c" est bien pratique, c'est un type intégral qui ne balance jamais
d'exceptions et qui se manipule simplement. Autant déplacer le formatage
dans la fonction censée le faire (cf plus bas). En fait, il y a une
distinction interessante à faire ici : "c" - qui contient le code d'erreur
produit - est la véritable information contenue par ton exception, celle que
tu vas utiliser pour prendre des décision autres que du pur formatage
d'erreur, alors que "exp" est juste une représentation de "c" destinée à
l'utilisateur/développeur. Et il est même assez discutable de mettre "exp"
dans la classe gèrant l'exception, le formatage étant indépendant de la
nature de l'exception (c'est plus une question de langues, de méthode
d'affichage, etc...).
Tu pourrais utiliser une énumération ici.
Voire :
Erreur(const Erreur &s);
à moins que tu ne fasses des trucs étranges dans tes constructeurs de copie.
Erreur(int a);
Si jamais tu envisages de dériver de Erreur, pense à ajouter un destructeur
virtuel.
Erreur a(Erreur::dbzero);
throw(a);
Ou encore :
throw Erreur(Erreur::dbzero);
Patrick Mézard
Quelques remarques d'implémentation. Tu pourras trouver des détails
intéressants à ce sujet là :
http://www.boost.org/more/error_handling.html
Il est souvent pratique de faire dériver ses exceptions de std::exception ou
d'une de ses sous-classes. Ca facilite grandement la gestion des erreurs
dans le cas où on n'a pas besoin d'une grande finesse.
{
private:
int c;
string exp;
Aïe, aïe, aïe. C'est bien de vouloir formater les messages d'erreur avec des
std::string. Le problème c'est que la construction de la chaîne peut lever
une exception, et que ça devient assez problèmatique dans un contexte de
gestion d'exception. Si tu as vraiment besoin d'un message, ou bien
restreint toi à un buffer statique ou bien alloue le à la main en gèrant
correctement les erreurs potentielles. Dans ton cas, "exp" n'est pas
vraiment utile : elle contient la description de l'erreur codée dans "c".
Or
"c" est bien pratique, c'est un type intégral qui ne balance jamais
d'exceptions et qui se manipule simplement. Autant déplacer le formatage
dans la fonction censée le faire (cf plus bas). En fait, il y a une
distinction interessante à faire ici : "c" - qui contient le code d'erreur
produit - est la véritable information contenue par ton exception, celle que
tu vas utiliser pour prendre des décision autres que du pur formatage
d'erreur, alors que "exp" est juste une représentation de "c" destinée à
l'utilisateur/développeur. Et il est même assez discutable de mettre "exp"
dans la classe gèrant l'exception, le formatage étant indépendant de la
nature de l'exception (c'est plus une question de langues, de méthode
d'affichage, etc...).
Tu pourrais utiliser une énumération ici.
Voire :
Erreur(const Erreur &s);
à moins que tu ne fasses des trucs étranges dans tes constructeurs de copie.
Erreur(int a);
Si jamais tu envisages de dériver de Erreur, pense à ajouter un destructeur
virtuel.
Erreur a(Erreur::dbzero);
throw(a);
Ou encore :
throw Erreur(Erreur::dbzero);
Patrick Mézard
Quelques remarques d'implémentation. Tu pourras trouver des détails
intéressants à ce sujet là :
http://www.boost.org/more/error_handling.html
Il est souvent pratique de faire dériver ses exceptions de std::exception ou
d'une de ses sous-classes. Ca facilite grandement la gestion des erreurs
dans le cas où on n'a pas besoin d'une grande finesse.
{
private:
int c;
string exp;
Aïe, aïe, aïe. C'est bien de vouloir formater les messages d'erreur avec des
std::string. Le problème c'est que la construction de la chaîne peut lever
une exception, et que ça devient assez problèmatique dans un contexte de
gestion d'exception. Si tu as vraiment besoin d'un message, ou bien
restreint toi à un buffer statique ou bien alloue le à la main en gèrant
correctement les erreurs potentielles. Dans ton cas, "exp" n'est pas
vraiment utile : elle contient la description de l'erreur codée dans "c".
Or
"c" est bien pratique, c'est un type intégral qui ne balance jamais
d'exceptions et qui se manipule simplement. Autant déplacer le formatage
dans la fonction censée le faire (cf plus bas). En fait, il y a une
distinction interessante à faire ici : "c" - qui contient le code d'erreur
produit - est la véritable information contenue par ton exception, celle que
tu vas utiliser pour prendre des décision autres que du pur formatage
d'erreur, alors que "exp" est juste une représentation de "c" destinée à
l'utilisateur/développeur. Et il est même assez discutable de mettre "exp"
dans la classe gèrant l'exception, le formatage étant indépendant de la
nature de l'exception (c'est plus une question de langues, de méthode
d'affichage, etc...).
Tu pourrais utiliser une énumération ici.
Voire :
Erreur(const Erreur &s);
à moins que tu ne fasses des trucs étranges dans tes constructeurs de copie.
Erreur(int a);
Si jamais tu envisages de dériver de Erreur, pense à ajouter un destructeur
virtuel.
Erreur a(Erreur::dbzero);
throw(a);
Ou encore :
throw Erreur(Erreur::dbzero);
Patrick Mézard
ok merci, j'ai fait ce genre de pratique à peu près :
et dans une fonction par exemple je fais :
dans mon main de test, j'utilise try/catch pour tester le code :
ok merci, j'ai fait ce genre de pratique à peu près :
et dans une fonction par exemple je fais :
dans mon main de test, j'utilise try/catch pour tester le code :
ok merci, j'ai fait ce genre de pratique à peu près :
et dans une fonction par exemple je fais :
dans mon main de test, j'utilise try/catch pour tester le code :
"Nicolas Aunai" a écrit dans le message de
news:dans le cas où l'utilisateur veut accéder a une case d'un tableau
nxm et que la case demandée dépasse les dimensions du tableau,
j'aimerai lancer une exception...
Bonne pratique.
"Nicolas Aunai" <nicolas.aunai@free.fr> a écrit dans le message de
news:mesnews.8b397d41.bdd90473.8.1437@free.fr...
dans le cas où l'utilisateur veut accéder a une case d'un tableau
nxm et que la case demandée dépasse les dimensions du tableau,
j'aimerai lancer une exception...
Bonne pratique.
"Nicolas Aunai" a écrit dans le message de
news:dans le cas où l'utilisateur veut accéder a une case d'un tableau
nxm et que la case demandée dépasse les dimensions du tableau,
j'aimerai lancer une exception...
Bonne pratique.
"Frédéric Gourul" wrote in message
news:<bubk42$na0$..."Nicolas Aunai" a écrit dans le message de
news:
Ça dépend. Si son « utilisateur », c'est l'utilisateur du programme,
c-à-d un homme qui entre le numéro au clavier, c'est probablement une
mauvaise idée. C'est en général mieux de faire des contrôles de validité
immédiatement au moment de l'entrée, et de traiter l'erreur localement
(à peu près au même niveau que s'il entre un caractère non numérique).
Si par utilisateur, en revanche, il veut dire le code client, la plupart
du temps, le respect des bornes du tableau est une précondition, leur
non-respect est une violation du contrat, et lever une exception est
prèsque toujours une mauvaise solution.
"Frédéric Gourul" <fgourul.nospam@9online.fr> wrote in message
news:<bubk42$na0$1@apollon.grec.isp.9tel.net>...
"Nicolas Aunai" <nicolas.aunai@free.fr> a écrit dans le message de
news:mesnews.8b397d41.bdd90473.8.1437@free.fr...
Ça dépend. Si son « utilisateur », c'est l'utilisateur du programme,
c-à-d un homme qui entre le numéro au clavier, c'est probablement une
mauvaise idée. C'est en général mieux de faire des contrôles de validité
immédiatement au moment de l'entrée, et de traiter l'erreur localement
(à peu près au même niveau que s'il entre un caractère non numérique).
Si par utilisateur, en revanche, il veut dire le code client, la plupart
du temps, le respect des bornes du tableau est une précondition, leur
non-respect est une violation du contrat, et lever une exception est
prèsque toujours une mauvaise solution.
"Frédéric Gourul" wrote in message
news:<bubk42$na0$..."Nicolas Aunai" a écrit dans le message de
news:
Ça dépend. Si son « utilisateur », c'est l'utilisateur du programme,
c-à-d un homme qui entre le numéro au clavier, c'est probablement une
mauvaise idée. C'est en général mieux de faire des contrôles de validité
immédiatement au moment de l'entrée, et de traiter l'erreur localement
(à peu près au même niveau que s'il entre un caractère non numérique).
Si par utilisateur, en revanche, il veut dire le code client, la plupart
du temps, le respect des bornes du tableau est une précondition, leur
non-respect est une violation du contrat, et lever une exception est
prèsque toujours une mauvaise solution.
Pourquoi serait-ce une mauvaise solution ?
Il est vrai que
vector::operator[] ne lève pas d'exception
Pourquoi serait-ce une mauvaise solution ?
Il est vrai que
vector::operator[] ne lève pas d'exception
Pourquoi serait-ce une mauvaise solution ?
Il est vrai que
vector::operator[] ne lève pas d'exception
On Mon, 19 Jan 2004 15:45:16 +0100, "Frédéric Gourul"
wrote:Pourquoi serait-ce une mauvaise solution ?
AMHA, il voulait dire "bonne solution".
On Mon, 19 Jan 2004 15:45:16 +0100, "Frédéric Gourul"
<fgourul.nospam@desysif.fr> wrote:
Pourquoi serait-ce une mauvaise solution ?
AMHA, il voulait dire "bonne solution".
On Mon, 19 Jan 2004 15:45:16 +0100, "Frédéric Gourul"
wrote:Pourquoi serait-ce une mauvaise solution ?
AMHA, il voulait dire "bonne solution".