Re: initialiser variable constante dans le constructeur
On 13 avr, 15:39, Pascal Bourguignon <p...@informatimago.com> wrote:
> James Kanze <james.ka...@gmail.com> writes:
> > Fabien a montré la solution classique, mais il faut signaler que
> > s'il s'agit de plusieurs valeurs, dans une seule chaîne de
> > caractères, la solution est loin d'être optimale, parce qu'il
> > faudrait récréer la istringstream pour chaque valeur, sautant
> > les valeurs qu'on ne recherche pas chaque fois.
> Quel manque d'imagination!
Tu as oublié l'émoticon:-).
> class C
> {
> public:
> C(std::string const&);
> inline int getA(void) const {return a;}
> inline int getB(void) const {return b;}
> private:
> int const a;
> int const b;
> int getParameter(std::string const& arguments,unsigned int n);
> };
> C::C(std::string const& param)
> : a(getParameter(param,1)),
> b(getParameter(param,2))
> {}
> int C::getParameter(std::string const& arguments,unsigned int n){
> typedef std::map<std::string,std::vector<int> > ParameterCache;
> static ParameterCache cache;
> ParameterCache::iterator parameters=cache.find(arguments);
> if(parameters==cache.end()){
> std::istringstream in(arguments);
> std::vector<int> parsedArgs;
> while(not(in.eof())){
(Je sais que ta proposition est ironique, mais je tiens à
signaler en passant quand même qu'avec ce test, tu risques de
traiter un paramètre en trop, avec un comportement indéfini.)
> int argument;
> in>>argument;
> parsedArgs.push_back(argument);
> }
> cache[arguments]=parsedArgs;
> parameters=cache.find(arguments);
> }
> if(parameters->second.size()<=n){
> throw Error("Too few arguments");
> }
> return(parameters->second[n]);
> }
Avec une gestion d'erreurs correcte, des locks en plus si le
code est multi-thread, et assez de mémoire, effectivement, cette
solution pourrait marcher. Mais j'ai quand même comme une
impression que cette dernière considération va jouer contre elle
la plupart du temps.
> int main(void){
> C c0("0 1 2 3");
> C c1("10 11 12 13");
Tu aurais dû essayer:
C c3( "1\n" ) ;
Qui doit, je crois, provoque une erreur (mais qui ne le fait
probablement pas).
> std::cout<<"c0: "<<c0.getA()<<" "<<c0.getB()<<std::endl;
> std::cout<<"c1: "<<c1.getA()<<" "<<c1.getB()<<std::endl;
> return(0);
> }
> /*
> -*- mode: compilation; default-directory: "~/src/miscellaneous/tests-c++/"-*-
> Compilation started at Sun Apr 13 15:38:52
> g++ -o const-member const-member.c++ && ./const-member
> c0: 1 2
> c1: 11 12
> Compilation finished at Sun Apr 13 15:38:57
> */
Et maintenant, avec une boucle :
std::string line ;
while ( std::getline( std::cin, line ) ) {
C c( line ) ;
std::cout << getA() << ' ' << c.getB() << std::endl ;
}
Avec en entrée, un fichier avec des milliards de lignes
différentes.
On pourrait imaginer quelque chose de ce genre, avec, disons :
class C
{
static std::istringstream parser ;
C( std::string const& init )
: a( getFirst( init ) )
, b( getNext() )
{
parser >> std::ws ;
if ( ! parser || parser.get() != EOF ) {
throw uneErrorDeSyntax ;
}
}
static int getFirst( std::string const& init )
{
parser.str( init ) ;
int result ;
init >> result ;
return result ;
}
static int getNext()
{
int result ;
init >> result ;
return result ;
}
// ...
} ;
C'est quand même assez fragile (puisqu'il dépend de l'ordre des
initialisations), et évidemment, dès qu'il y a des threads...
(On peut aussi le rendre thread-safe, mais c'est encore plus
exotique.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
|