PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > fr.comp.lang.c++ > initialiser variable constante dans le constructeur
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
initialiser variable constante dans le constructeur

Réponse
 
LinkBack Outils de la discussion
Vieux 12/04/2008, 13h52   #1
David Côme
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut initialiser variable constante dans le constructeur

Bonjour à tous.

Je recois en paramètre d'une classe une chaîne qui contient plusieurs
valeurs (des ints pour être précis).
Dans mon constructeur, je récupère ces variables via des *stringstream.
Jusque lÃ, pas de problème.

La difficulté vient du fait que je souhaite ensuite affecter les valeurs
obtenues à des variables constantes
car les valeurs récupérées sont les valeurs que doivent avoir les
variables constantes.

Je ne peux donc pas donner de valeurs aux constantes dans la liste
d'initialisation puisque les valeurs ne sont pas encore connues.

Une idée ?

Merci.
  Réponse avec citation
Vieux 12/04/2008, 13h53   #2
Fabien LE LEZ
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: initialiser variable constante dans le constructeur

On Sat, 12 Apr 2008 14:52:10 +0200, David Côme <davidcome@wanadoo.fr>:

>Je ne peux donc pas donner de valeurs aux constantes dans la liste
>d'initialisation puisque les valeurs ne sont pas encore connues.


class C
{
public:
C (std::string const&);
private:
int const a;
int const b;
};

C::C (std::string const& param)
: a (GetParametre (param, 1))
, b (GetParametre (param, 2))
{}



GetParametre (string const&, unsigned int n)
est bien sûr une fonction qui découpe la chaîne et renvoie le n-ième
entier.

  Réponse avec citation
Vieux 12/04/2008, 14h23   #3
David Côme
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: initialiser variable constante dans le constructeur

On Sat, 12 Apr 2008 14:53:51 +0200, Fabien LE LEZ <gramster@gramster.com>
wrote:

> On Sat, 12 Apr 2008 14:52:10 +0200, David Côme <davidcome@wanadoo.fr>:
>
>> Je ne peux donc pas donner de valeurs aux constantes dans la liste
>> d'initialisation puisque les valeurs ne sont pas encore connues.

>
> class C
> {
> public:
> C (std::string const&);
> private:
> int const a;
> int const b;
> };
>
> C::C (std::string const& param)
> : a (GetParametre (param, 1))
> , b (GetParametre (param, 2))
> {}
>
>
> Où
> GetParametre (string const&, unsigned int n)
> est bien sûr une fonction qui découpe la chaîne et renvoie le n-ième
> entier.
>



Ok, merci.
  Réponse avec citation
Vieux 13/04/2008, 09h29   #4
James Kanze
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: initialiser variable constante dans le constructeur

On 12 avr, 14:52, David Côme <davidc...@wanadoo.fr> wrote:

> Je recois en paramètre d'une classe une chaîne qui contient
> plusieurs valeurs (des ints pour être précis). Dans mon
> constructeur, je récupère ces variables via des *stringstream.
> Jusque là, pas de problème.


> La difficulté vient du fait que je souhaite ensuite affecter
> les valeurs obtenues à des variables constantes car les
> valeurs récupérées sont les valeurs que doivent avoir les
> variables constantes.


> Je ne peux donc pas donner de valeurs aux constantes dans la
> liste d'initialisation puisque les valeurs ne sont pas encore
> connues.


> Une idée ?


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. Dans ces cas-ci,
je me démande si le const vaut la peine. Const est surtout utile
au niveau des arguments d'une fonction ou des variables globales
(à cause des garanties qu'il promet), ou sinon quand il s'agit
d'une expression integrale constante (parce que certaines
constructions dans le langage l'exige). Ici, il s'agit
uniquement à des variables qui ne sont de toute façon pas
accessibles aux autres, et qui ne peuvent pas non plus servir
dans des expressions const. Du coup, le const se résume à une
petite promesse à toi-même.

Dans la pratique, je n'utilise pour ainsi dire jamais const sur
des variables locales ou membres privés.

--
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
  Réponse avec citation
Vieux 13/04/2008, 14h39   #5
Pascal Bourguignon
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: initialiser variable constante dans le constructeur

James Kanze <james.kanze@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!

#include <ciso646>
#include <map>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <iterator>
#include <exception>

class Error:public std::exception {
std::string message;
public:
Error(std::string const& aMessage):message(aMessage){};
~Error(void)throw(){};
const char* what(void){return(message.c_str());}
};

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())){
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]);
}

int main(void){
C c0("0 1 2 3");
C c1("10 11 12 13");
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
*/


--
__Pascal Bourguignon__ http://www.informatimago.com/

NEW GRAND UNIFIED THEORY DISCLAIMER: The manufacturer may
technically be entitled to claim that this product is
ten-dimensional. However, the consumer is reminded that this
confers no legal rights above and beyond those applicable to
three-dimensional objects, since the seven new dimensions are
"rolled up" into such a small "area" that they cannot be
detected.
  Réponse avec citation
Vieux 13/04/2008, 15h27   #6
James Kanze
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut 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
  Réponse avec citation
Vieux 13/04/2008, 15h31   #7
David Côme
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: initialiser variable constante dans le constructeur

On Sun, 13 Apr 2008 15:39:49 +0200, Pascal Bourguignon
<pjb@informatimago.com> wrote:

> James Kanze <james.kanze@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!
>
> #include <ciso646>
> #include <map>
> #include <string>
> #include <vector>
> #include <sstream>
> #include <iostream>
> #include <iterator>
> #include <exception>
>
> class Error:public std::exception {
> std::string message;
> public:
> Error(std::string const& aMessage):message(aMessage){};
> ~Error(void)throw(){};
> const char* what(void){return(message.c_str());}
> };
>
> 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())){
> 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]);
> }
>
> int main(void){
> C c0("0 1 2 3");
> C c1("10 11 12 13");
> 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
> */
>
>


C'est une très belle solution mais après réflexion , j'ai l'impression que
je sort un tank pour
écraser 2 mouches.
  Réponse avec citation
Vieux 14/04/2008, 10h58   #8
Olivier Miakinen
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: initialiser variable constante dans le constructeur

Le 13/04/2008 16:31, David Côme a écrit :
>
> C'est une très belle solution mais après réflexion, j'ai l'impression que
> je sors un tank pour écraser 2 mouches.


J'aime bien le « après réflexion ». ;-)
  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 03h41.


Édité par : vBulletin® version 3.7.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,21752 seconds with 16 queries