Bonjour, je veux définir ma propre hiérarchie de classes d'exception
dans mon namespace My. J'aimerais que toutes mes exceptions dérivent de
My::Error (elle même une sous-classe de std::exception). Mais j'aimerais
aussi pouvoir hériter d'autres exceptions standards.
Voici un main de test qui (je pense) reflète ce que je désire.
int main()
{
My::Error *e = 0;
static_cast<std::exception*>(e);
My::RuntimeError *re = 0;
static_cast<My::Error*>(re);
static_cast<std::exception*>(re);
static_cast<std::runtime_error*>(re);
}
Ce qui me permettrait d'attraper au choix :
- toute std::exception
- toute My:Error
- toute std::runtime_error
Je ne pense pas que ce soit une exigence farfelue.
Mais je coince au niveau de l'implémentation, ComeauOnline n'y trouve
rien à redire, mais les différentes version de g++ que j'ai à ma
disposition n'apprécie pas.
erreur: « std::exception » est une base ambiguë de « My::RuntimeError »
Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas correcte.
Voici où j'en suis :
#include <stdexcept>
#include <string>
namespace My
{
class Error : public std::exception
{
public:
~Error() throw() { }
};
Bonjour, je veux définir ma propre hiérarchie de classes d'exception
dans mon namespace My. J'aimerais que toutes mes exceptions dérivent de
My::Error (elle même une sous-classe de std::exception). Mais j'aimerais
aussi pouvoir hériter d'autres exceptions standards.
Voici un main de test qui (je pense) reflète ce que je désire.
int main()
{
My::Error *e = 0;
static_cast<std::exception*>(e);
My::RuntimeError *re = 0;
static_cast<My::Error*>(re);
static_cast<std::exception*>(re);
static_cast<std::runtime_error*>(re);
}
Ce qui me permettrait d'attraper au choix :
- toute std::exception
- toute My:Error
- toute std::runtime_error
Je ne pense pas que ce soit une exigence farfelue.
Mais je coince au niveau de l'implémentation, ComeauOnline n'y trouve
rien à redire, mais les différentes version de g++ que j'ai à ma
disposition n'apprécie pas.
erreur: « std::exception » est une base ambiguë de « My::RuntimeError »
Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas correcte.
Voici où j'en suis :
#include <stdexcept>
#include <string>
namespace My
{
class Error : public std::exception
{
public:
~Error() throw() { }
};
Bonjour, je veux définir ma propre hiérarchie de classes d'exception
dans mon namespace My. J'aimerais que toutes mes exceptions dérivent de
My::Error (elle même une sous-classe de std::exception). Mais j'aimerais
aussi pouvoir hériter d'autres exceptions standards.
Voici un main de test qui (je pense) reflète ce que je désire.
int main()
{
My::Error *e = 0;
static_cast<std::exception*>(e);
My::RuntimeError *re = 0;
static_cast<My::Error*>(re);
static_cast<std::exception*>(re);
static_cast<std::runtime_error*>(re);
}
Ce qui me permettrait d'attraper au choix :
- toute std::exception
- toute My:Error
- toute std::runtime_error
Je ne pense pas que ce soit une exigence farfelue.
Mais je coince au niveau de l'implémentation, ComeauOnline n'y trouve
rien à redire, mais les différentes version de g++ que j'ai à ma
disposition n'apprécie pas.
erreur: « std::exception » est une base ambiguë de « My::RuntimeError »
Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas correcte.
Voici où j'en suis :
#include <stdexcept>
#include <string>
namespace My
{
class Error : public std::exception
{
public:
~Error() throw() { }
};
"Benoît Dejean" a écrit dans le message de
news:
Bonjour, je veux définir ma propre hiérarchie de classes
d'exception dans mon namespace My. J'aimerais que toutes mes
exceptions dérivent de My::Error (elle même une sous-classe
de std::exception). Mais j'aimerais aussi pouvoir hériter
d'autres exceptions standards.
Voici un main de test qui (je pense) reflète ce que je désire.
int main()
{
My::Error *e = 0;
static_cast<std::exception*>(e);
My::RuntimeError *re = 0;
static_cast<My::Error*>(re);
static_cast<std::exception*>(re);
static_cast<std::runtime_error*>(re);
}
Ce qui me permettrait d'attraper au choix :
- toute std::exception
- toute My:Error
- toute std::runtime_error
Je ne pense pas que ce soit une exigence farfelue.
Mais je coince au niveau de l'implémentation, ComeauOnline
n'y trouve rien à redire, mais les différentes version de
g++ que j'ai à ma disposition n'apprécie pas.
erreur: « std::exception » est une base ambiguë de «
My::RuntimeError »
Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas
correcte.
Voici où j'en suis :
#include <stdexcept>
#include <string>
namespace My
{
class Error : public std::exception
{
public:
~Error() throw() { }
};
Simple question qui n'a rien avoir avec le problème posé: Est
ce que rajouter la spécification "throw()" à un destructeur
est considéré comme une bonne pratique?
Si oui pourquoi n'est ce pas plus répandu?
c'est la première fois que je tombe dessus...
"Benoît Dejean" <tazforever@free.fr> a écrit dans le message de
news:
pan.2005.05.08.22.28.00.683957@free.fr...
Bonjour, je veux définir ma propre hiérarchie de classes
d'exception dans mon namespace My. J'aimerais que toutes mes
exceptions dérivent de My::Error (elle même une sous-classe
de std::exception). Mais j'aimerais aussi pouvoir hériter
d'autres exceptions standards.
Voici un main de test qui (je pense) reflète ce que je désire.
int main()
{
My::Error *e = 0;
static_cast<std::exception*>(e);
My::RuntimeError *re = 0;
static_cast<My::Error*>(re);
static_cast<std::exception*>(re);
static_cast<std::runtime_error*>(re);
}
Ce qui me permettrait d'attraper au choix :
- toute std::exception
- toute My:Error
- toute std::runtime_error
Je ne pense pas que ce soit une exigence farfelue.
Mais je coince au niveau de l'implémentation, ComeauOnline
n'y trouve rien à redire, mais les différentes version de
g++ que j'ai à ma disposition n'apprécie pas.
erreur: « std::exception » est une base ambiguë de «
My::RuntimeError »
Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas
correcte.
Voici où j'en suis :
#include <stdexcept>
#include <string>
namespace My
{
class Error : public std::exception
{
public:
~Error() throw() { }
};
Simple question qui n'a rien avoir avec le problème posé: Est
ce que rajouter la spécification "throw()" à un destructeur
est considéré comme une bonne pratique?
Si oui pourquoi n'est ce pas plus répandu?
c'est la première fois que je tombe dessus...
"Benoît Dejean" a écrit dans le message de
news:
Bonjour, je veux définir ma propre hiérarchie de classes
d'exception dans mon namespace My. J'aimerais que toutes mes
exceptions dérivent de My::Error (elle même une sous-classe
de std::exception). Mais j'aimerais aussi pouvoir hériter
d'autres exceptions standards.
Voici un main de test qui (je pense) reflète ce que je désire.
int main()
{
My::Error *e = 0;
static_cast<std::exception*>(e);
My::RuntimeError *re = 0;
static_cast<My::Error*>(re);
static_cast<std::exception*>(re);
static_cast<std::runtime_error*>(re);
}
Ce qui me permettrait d'attraper au choix :
- toute std::exception
- toute My:Error
- toute std::runtime_error
Je ne pense pas que ce soit une exigence farfelue.
Mais je coince au niveau de l'implémentation, ComeauOnline
n'y trouve rien à redire, mais les différentes version de
g++ que j'ai à ma disposition n'apprécie pas.
erreur: « std::exception » est une base ambiguë de «
My::RuntimeError »
Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas
correcte.
Voici où j'en suis :
#include <stdexcept>
#include <string>
namespace My
{
class Error : public std::exception
{
public:
~Error() throw() { }
};
Simple question qui n'a rien avoir avec le problème posé: Est
ce que rajouter la spécification "throw()" à un destructeur
est considéré comme une bonne pratique?
Si oui pourquoi n'est ce pas plus répandu?
c'est la première fois que je tombe dessus...
SerGioGio wrote:"Benoît Dejean" a écrit dans le message de
news:Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas
correcte.
C'est effectivement le problème de base.
Dans la pratique, la seule solution que je vois, c'est que les
classes de base dans ton hiérarchie ne dérive pas de
std::exception, mais fonctionnent comme des mixins. Et que tu ne
fusionnes les deux hiérarchies qu'à un niveau plus élevé, quand
tu sais la classe exacte de l'hiérarchie standard dont tu as
besoin. C'est un peu pénible, mais avec l'aide des templates,
faisable.
SerGioGio wrote:
"Benoît Dejean" <tazforever@free.fr> a écrit dans le message de
news:
Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas
correcte.
C'est effectivement le problème de base.
Dans la pratique, la seule solution que je vois, c'est que les
classes de base dans ton hiérarchie ne dérive pas de
std::exception, mais fonctionnent comme des mixins. Et que tu ne
fusionnes les deux hiérarchies qu'à un niveau plus élevé, quand
tu sais la classe exacte de l'hiérarchie standard dont tu as
besoin. C'est un peu pénible, mais avec l'aide des templates,
faisable.
SerGioGio wrote:"Benoît Dejean" a écrit dans le message de
news:Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas
correcte.
C'est effectivement le problème de base.
Dans la pratique, la seule solution que je vois, c'est que les
classes de base dans ton hiérarchie ne dérive pas de
std::exception, mais fonctionnent comme des mixins. Et que tu ne
fusionnes les deux hiérarchies qu'à un niveau plus élevé, quand
tu sais la classe exacte de l'hiérarchie standard dont tu as
besoin. C'est un peu pénible, mais avec l'aide des templates,
faisable.
SerGioGio wrote:"Benoît Dejean" a écrit dans le message de
news:
Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas
correcte.
C'est effectivement le problème de base.
Dans la pratique, la seule solution que je vois, c'est que
les classes de base dans ton hiérarchie ne dérive pas de
std::exception, mais fonctionnent comme des mixins. Et que
tu ne fusionnes les deux hiérarchies qu'à un niveau plus
élevé, quand tu sais la classe exacte de l'hiérarchie
standard dont tu as besoin. C'est un peu pénible, mais avec
l'aide des templates, faisable.
c'est à dire ?
quelque chose comme ça ?
#include <stdexcept>
#include <string>
namespace My
{
class Error
{
public:
virtual void
raise_std_exception() = 0;
virtual std::exception&
std_exception() = 0;
virtual ~Error() throw()
{ }
};
template<typename T>
class ErrorT : public T, public Error
{
public:
explicit ErrorT(const std::string& s)
: T(s)
{ }
void
raise_std_exception()
{
throw this->std_exception();
}
virtual T&
std_exception()
{
return *this;
}
virtual ~ErrorT() throw()
{ }
};
class RuntimeError : public ErrorT<std::runtime_error>
{
public:
explicit RuntimeError(const std::string& s)
: ErrorT<std::runtime_error>(s)
{ }
virtual ~RuntimeError() throw()
{ }
};
}
est-ce valide ?
est-ce que mes fonctions membres std_exception() sont
nécessaires ou est-ce qu'un dynamic_cast de My::Error& en
std::exception& est envisageable (c'est à dire naviguer
jusqu'à la base soeur) ?
SerGioGio wrote:
"Benoît Dejean" <tazforever@free.fr> a écrit dans le message de
news:
Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas
correcte.
C'est effectivement le problème de base.
Dans la pratique, la seule solution que je vois, c'est que
les classes de base dans ton hiérarchie ne dérive pas de
std::exception, mais fonctionnent comme des mixins. Et que
tu ne fusionnes les deux hiérarchies qu'à un niveau plus
élevé, quand tu sais la classe exacte de l'hiérarchie
standard dont tu as besoin. C'est un peu pénible, mais avec
l'aide des templates, faisable.
c'est à dire ?
quelque chose comme ça ?
#include <stdexcept>
#include <string>
namespace My
{
class Error
{
public:
virtual void
raise_std_exception() = 0;
virtual std::exception&
std_exception() = 0;
virtual ~Error() throw()
{ }
};
template<typename T>
class ErrorT : public T, public Error
{
public:
explicit ErrorT(const std::string& s)
: T(s)
{ }
void
raise_std_exception()
{
throw this->std_exception();
}
virtual T&
std_exception()
{
return *this;
}
virtual ~ErrorT() throw()
{ }
};
class RuntimeError : public ErrorT<std::runtime_error>
{
public:
explicit RuntimeError(const std::string& s)
: ErrorT<std::runtime_error>(s)
{ }
virtual ~RuntimeError() throw()
{ }
};
}
est-ce valide ?
est-ce que mes fonctions membres std_exception() sont
nécessaires ou est-ce qu'un dynamic_cast de My::Error& en
std::exception& est envisageable (c'est à dire naviguer
jusqu'à la base soeur) ?
SerGioGio wrote:"Benoît Dejean" a écrit dans le message de
news:
Deplus, std::exception n'étant pas une base virtuelle de
std::runtime_error, mon héritage en losange n'est pas
correcte.
C'est effectivement le problème de base.
Dans la pratique, la seule solution que je vois, c'est que
les classes de base dans ton hiérarchie ne dérive pas de
std::exception, mais fonctionnent comme des mixins. Et que
tu ne fusionnes les deux hiérarchies qu'à un niveau plus
élevé, quand tu sais la classe exacte de l'hiérarchie
standard dont tu as besoin. C'est un peu pénible, mais avec
l'aide des templates, faisable.
c'est à dire ?
quelque chose comme ça ?
#include <stdexcept>
#include <string>
namespace My
{
class Error
{
public:
virtual void
raise_std_exception() = 0;
virtual std::exception&
std_exception() = 0;
virtual ~Error() throw()
{ }
};
template<typename T>
class ErrorT : public T, public Error
{
public:
explicit ErrorT(const std::string& s)
: T(s)
{ }
void
raise_std_exception()
{
throw this->std_exception();
}
virtual T&
std_exception()
{
return *this;
}
virtual ~ErrorT() throw()
{ }
};
class RuntimeError : public ErrorT<std::runtime_error>
{
public:
explicit RuntimeError(const std::string& s)
: ErrorT<std::runtime_error>(s)
{ }
virtual ~RuntimeError() throw()
{ }
};
}
est-ce valide ?
est-ce que mes fonctions membres std_exception() sont
nécessaires ou est-ce qu'un dynamic_cast de My::Error& en
std::exception& est envisageable (c'est à dire naviguer
jusqu'à la base soeur) ?
Si tu veux enforcer la politique que toute exception dérive
aussi d'une exception standard, tu pourrais faire quelque chose
du genre :
void // publique, non-virtuelle !!
Error::raise()
{
assert( dynamic_cast< std::exception* >( this ) != NULL ) ;
doRaise() ; // privée, virtuelle pûre.
}
Mais évidemment, ça n'apporte quelque chose que si tes tests
unitaires lèvent bien l'exception en question. (En théorie, les
tests unitaires doivent tester tout, y compris tous les cas
possible d'erreur. Dans la pratique, souvent...)
Si tu veux enforcer la politique que toute exception dérive
aussi d'une exception standard, tu pourrais faire quelque chose
du genre :
void // publique, non-virtuelle !!
Error::raise()
{
assert( dynamic_cast< std::exception* >( this ) != NULL ) ;
doRaise() ; // privée, virtuelle pûre.
}
Mais évidemment, ça n'apporte quelque chose que si tes tests
unitaires lèvent bien l'exception en question. (En théorie, les
tests unitaires doivent tester tout, y compris tous les cas
possible d'erreur. Dans la pratique, souvent...)
Si tu veux enforcer la politique que toute exception dérive
aussi d'une exception standard, tu pourrais faire quelque chose
du genre :
void // publique, non-virtuelle !!
Error::raise()
{
assert( dynamic_cast< std::exception* >( this ) != NULL ) ;
doRaise() ; // privée, virtuelle pûre.
}
Mais évidemment, ça n'apporte quelque chose que si tes tests
unitaires lèvent bien l'exception en question. (En théorie, les
tests unitaires doivent tester tout, y compris tous les cas
possible d'erreur. Dans la pratique, souvent...)
wrote:Si tu veux enforcer la politique que toute exception dérive
aussi d'une exception standard, tu pourrais faire quelque
chose du genre :
void // publique, non-virtuelle !!
Error::raise()
{
assert( dynamic_cast< std::exception* >( this ) != NULL ) ;
doRaise() ; // privée, virtuelle pûre.
}
Mais évidemment, ça n'apporte quelque chose que si tes tests
unitaires lèvent bien l'exception en question. (En théorie,
les tests unitaires doivent tester tout, y compris tous les
cas possible d'erreur. Dans la pratique, souvent...)
Alors, pour ça j'ai tendance à utiliser des "type safes macros"
#define THROW(e)
do{
throw e;
const std::exception& dummy_ref = e;
}while(0)
et faire "grep throw" sur mon code source. Il ne doit y en
avoir qu'un seul. Par contre, il peut y avoir pleins de
résultats à grep THROW.
(Comme ça plus besoin de tests unitaires :-)
kanze@gabi-soft.fr wrote:
Si tu veux enforcer la politique que toute exception dérive
aussi d'une exception standard, tu pourrais faire quelque
chose du genre :
void // publique, non-virtuelle !!
Error::raise()
{
assert( dynamic_cast< std::exception* >( this ) != NULL ) ;
doRaise() ; // privée, virtuelle pûre.
}
Mais évidemment, ça n'apporte quelque chose que si tes tests
unitaires lèvent bien l'exception en question. (En théorie,
les tests unitaires doivent tester tout, y compris tous les
cas possible d'erreur. Dans la pratique, souvent...)
Alors, pour ça j'ai tendance à utiliser des "type safes macros"
#define THROW(e)
do{
throw e;
const std::exception& dummy_ref = e;
}while(0)
et faire "grep throw" sur mon code source. Il ne doit y en
avoir qu'un seul. Par contre, il peut y avoir pleins de
résultats à grep THROW.
(Comme ça plus besoin de tests unitaires :-)
wrote:Si tu veux enforcer la politique que toute exception dérive
aussi d'une exception standard, tu pourrais faire quelque
chose du genre :
void // publique, non-virtuelle !!
Error::raise()
{
assert( dynamic_cast< std::exception* >( this ) != NULL ) ;
doRaise() ; // privée, virtuelle pûre.
}
Mais évidemment, ça n'apporte quelque chose que si tes tests
unitaires lèvent bien l'exception en question. (En théorie,
les tests unitaires doivent tester tout, y compris tous les
cas possible d'erreur. Dans la pratique, souvent...)
Alors, pour ça j'ai tendance à utiliser des "type safes macros"
#define THROW(e)
do{
throw e;
const std::exception& dummy_ref = e;
}while(0)
et faire "grep throw" sur mon code source. Il ne doit y en
avoir qu'un seul. Par contre, il peut y avoir pleins de
résultats à grep THROW.
(Comme ça plus besoin de tests unitaires :-)