 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
AG Guest
|
Posted: Wed May 09, 2007 9:57 pm Post subject: Variable non nommée |
|
|
Bonjour,
Je suis sur un code dans lequel il y a la déclaration suivante, dans
le main :
int a=2;
A A(a);
ou A est une class contenant que des membres statiques:
class A
{
static int a1;
public:
A();
A(int);
static int geta(void);
}
J'ai un peu de mal avec cette "déclaration". En essayant de
comprendre, il s'agit d'une variable non nommée ? Ai-je bon ?
l'acces au membre a1 se fait par A::geta(). J'ai besoin de pouvoir
enregistrer la class dans un fichier. j'ai donc défini :
friend ostream & operator<<(ostream & o, A& m);
mais la variable crée par "A A(a);" n'est pas utilisable par ma
fonction. Pourriez vous m'expliquer pourquoi et dans quels cas on
utilise de telle variable "non nommée" ?
Merci d'avance,
Alexandre. |
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Wed May 09, 2007 10:20 pm Post subject: Re: Variable non nommée |
|
|
On Wed, 9 May 2007 18:57:39 +0200, "AG" <ag (AT) tb (DOT) fr>:
| Quote: | Je suis sur un code dans lequel il y a la déclaration suivante, dans
le main :
int a=2;
A A(a);
|
Pour le coup, j'ai moi aussi du mal à comprendre.
J'imagine qu'il s'agit d'une variable qui a le même nom qu'une classe,
et que par miracle, il n'y a pas collusion.
| Quote: | En essayant de
comprendre, il s'agit d'une variable non nommée ?
|
À ma connaissance, ça n'existe pas en C++.
| Quote: | class A
{
static int a1;
public:
A();
A(int);
static int geta(void);
|
Peux-tu nous donner le code du constructeur ?
Je m'attends au pire -- par exemple, une initialisation de la variable
membre static avec l'argument du constructeur.
Ce qui voudrait dire que le constructeur est bidon, ou plutôt mal
nommé, et qu'il faudrait écrire :
class A
{
public:
static void SetA (int nouvelle_valeur) { a1= nouvelle_valeur; }
static int GetA() { return a1; }
private:
static int a1;
};
int main()
{
int a=2;
A::SetA (a);
}
M'enfin bon, tout ça a l'air d'un beau bordel. |
|
| Back to top |
|
 |
Sylvain Guest
|
Posted: Thu May 10, 2007 3:55 am Post subject: Re: Variable non nommée |
|
|
Fabien LE LEZ wrote on 09/05/2007 19:20:
| Quote: |
M'enfin bon, tout ça a l'air d'un beau bordel.
|
ah ça !... ;)
Sylvain. |
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Thu May 10, 2007 9:11 am Post subject: Re: Variable non nommée |
|
|
On May 9, 7:20 pm, Fabien LE LEZ <grams...@gramster.com> wrote:
| Quote: | On Wed, 9 May 2007 18:57:39 +0200, "AG" <a...@tb.fr>:
Je suis sur un code dans lequel il y a la déclaration suivante, dans
le main :
int a=2;
A A(a);
Pour le coup, j'ai moi aussi du mal à comprendre.
J'imagine qu'il s'agit d'une variable qui a le même nom qu'une classe,
et que par miracle, il n'y a pas collusion.
|
Il n'y a pas de miracle. La portée de la variable ne commence
qu'à la fin du « declarator », c-à-d ici qu'au parenthèse
ouvrant. Jusque là, le A en dehors de la fonction reste
visible. Voir §3.3.1 : il y a même un exemple du même genre.
Toujours est-il que c'est le genre de chose à éviter, au moins
que tu vises l'obfuscation.
| Quote: | En essayant de
comprendre, il s'agit d'une variable non nommée ?
À ma connaissance, ça n'existe pas en C++.
|
Ça s'appelle un temporaire (ou un rvalue). Mais on n'a pas
l'habitude de les considérer comme des variables.
--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) 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 |
|
| Back to top |
|
 |
Michael DOUBEZ Guest
|
Posted: Thu May 10, 2007 9:11 am Post subject: Re: Variable non nommée |
|
|
AG a écrit :
| Quote: | je vous dévoile une partie du code :
class MTRand;
class RandomNumGenerator
{
static MTRand* ptMersenneTwister;
static int StartSeed;
public:
RandomNumGenerator();
RandomNumGenerator(int seed);
~RandomNumGenerator();
static void Init();
static void Init(int seed);
static double rand();
...
};
avec
RandomNumGenerator::RandomNumGenerator(int seed)
{
if (seed == 0)
Init(); // use random without seed if the argument is zero
else
Init(seed); // otherwise use a seed
}
void RandomNumGenerator::Init(int seed)
{
cout << "RandomNumGenerator::Init(int seed)" << endl;
if(ptMersenneTwister)
|
Dans ce cas, initialise ptMersenneTwister à NULL.
static MTRand* ptMersenneTwister=NULL;
| Quote: | delete ptMersenneTwister;
if (seed != 0)
ptMersenneTwister = new MTRand(seed);
else
ptMersenneTwister = new MTRand();
}
et dans le main :
int seed = 1234;
RandomNumGenerator RandomNumGenerator(seed);
Eviter la confusion nom/'nom de classe'. |
Attention à l'ordre d'initialisation des statiques. Ici, tu en a
plusieurs qui sont concurrentes:
seed
RandomNumGenerator
RandomNumGenerator::ptMersenneTwister
RandomNumGenerator::StartSeed
Tu peux transformer
const int seed = 1234;//en zone RO du code
Tu n'as pas d'intérêt à utiliser des fonctions et variable statiques de
class. Soit:
1 tu mets dans un namespace avec des systèmes de
singleton/initialisation
2 tu définis une class de nombe aléatoire et tu la rends statique
Ici tu fais un mix des deux.
La solution 2 serait:
class MTRand;
class RandomNumGenerator
{
MTRand* ptMersenneTwister;
static int StartSeed;
public:
RandomNumGenerator(int seed=0);
~RandomNumGenerator();
void Init(int seed);
double rand();
...
};
Si rand n'est pas utilisé dans d'autres initialisations statiques:
static const int seed = 1234;
RandomNumGenerator single(seed);
mais si c'est la cas, utiiser le singleton :
RandomNumGenerator& RandNumGene()
{
static const int seed = 1234;
static RandomNumGenerator single(seed);
return single;
}
Puis tu utilise:
RandNumGene().rand();
| Quote: | et de temps en temps des :
RandomNumGenerator::rand() pour avoir un nombre tiré aléatoirement.
Bien sur le programme plante de temps en temps, personne ne sait
pourquoi. J'ai besoin de savoir si ce genre de pratique (qui est
utilisé largement dans le code avec d'autres class) peut causer des
problemes. Merci de me soutenir et de pas me renvoyer dans mes
pennates en me disant simplement qu'on écrit pas du code comme ça  |
|
|
| Back to top |
|
 |
Laurent Deniau Guest
|
Posted: Thu May 10, 2007 9:11 am Post subject: Re: Variable non nommée |
|
|
James Kanze wrote:
| Quote: | On May 9, 7:20 pm, Fabien LE LEZ <grams...@gramster.com> wrote:
On Wed, 9 May 2007 18:57:39 +0200, "AG" <a...@tb.fr>:
Je suis sur un code dans lequel il y a la déclaration suivante, dans
le main :
int a=2;
A A(a);
Pour le coup, j'ai moi aussi du mal à comprendre.
J'imagine qu'il s'agit d'une variable qui a le même nom qu'une classe,
et que par miracle, il n'y a pas collusion.
Il n'y a pas de miracle. La portée de la variable ne commence
qu'à la fin du « declarator », c-à-d ici qu'au parenthèse
ouvrant. Jusque là, le A en dehors de la fonction reste
visible. Voir §3.3.1 : il y a même un exemple du même genre.
Toujours est-il que c'est le genre de chose à éviter, au moins
que tu vises l'obfuscation.
En essayant de
comprendre, il s'agit d'une variable non nommée ?
À ma connaissance, ça n'existe pas en C++.
Ça s'appelle un temporaire (ou un rvalue). Mais on n'a pas
l'habitude de les considérer comme des variables.
|
Il y a aussi les parametres des fonctions (que l'on peut assimiler a des
variables) qui peuvent ne pas etre nomme:
void func(int a, int)
{
// ..
}
a+, ld. |
|
| Back to top |
|
 |
Michael DOUBEZ Guest
|
Posted: Thu May 10, 2007 9:11 am Post subject: Re: Variable non nommée |
|
|
AG a écrit :
| Quote: | Bonjour,
[beau bordel]
l'acces au membre a1 se fait par A::geta(). J'ai besoin de pouvoir
enregistrer la class dans un fichier. j'ai donc défini :
friend ostream & operator<<(ostream & o, A& m);
mais la variable crée par "A A(a);" n'est pas utilisable par ma
fonction. Pourriez vous m'expliquer pourquoi et dans quels cas on
utilise de telle variable "non nommée" ?
|
As tu essayé de rendre le paramètre const:
friend ostream & operator<<(ostream & o, const A& m);
Ca permet de prendre des variable temporaire en paramètre. (Je n'ai pas
retrouvé la référence dans le standard - j'ai pas beaucoup cherché non
plus.)
Exemple:
#include <iostream>
using namespace std;
//la class A
class A
{
int a1;
public:
A(int a=0):a1(a){}
int geta()const{return this->a1;}
friend ostream & operator<<(ostream & o, const A& m);
};
// l'operateur de streaming
// si on enlève const, ça ne compile plus
ostream & operator<<(ostream & o, const A& m)
{
o<<m.geta();
return o;
}
int main()
{
A a(1);
//la ligne suivante ne compile plus si non-const
cout<<"Named "<<a<<" Unnamed "<<A(2)<<endl;
return 0;
}
Michael |
|
| Back to top |
|
 |
Jean-Marc Bourguet Guest
|
Posted: Thu May 10, 2007 9:11 am Post subject: Re: Variable non nommée |
|
|
James Kanze <james.kanze (AT) gmail (DOT) com> writes:
| Quote: | Ça s'appelle un temporaire (ou un rvalue). Mais on n'a pas
l'habitude de les considérer comme des variables.
|
La definition de variable etant pour moi "un objet nomme", une "variable non
nommee" serait donc pour moi un oxymore si la contradiction etait
volontaire.
Outre les temporaires, les objets alloues dynamiquement et les elements des
tableaux ne sont pas nommes.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org |
|
| Back to top |
|
 |
AG Guest
|
Posted: Thu May 10, 2007 9:11 am Post subject: Re: Variable non nommée |
|
|
je vous dévoile une partie du code :
class MTRand;
class RandomNumGenerator
{
static MTRand* ptMersenneTwister;
static int StartSeed;
public:
RandomNumGenerator();
RandomNumGenerator(int seed);
~RandomNumGenerator();
static void Init();
static void Init(int seed);
static double rand();
...
};
avec
RandomNumGenerator::RandomNumGenerator(int seed)
{
if (seed == 0)
Init(); // use random without seed if the argument is zero
else
Init(seed); // otherwise use a seed
}
void RandomNumGenerator::Init(int seed)
{
cout << "RandomNumGenerator::Init(int seed)" << endl;
if(ptMersenneTwister)
delete ptMersenneTwister;
if (seed != 0)
ptMersenneTwister = new MTRand(seed);
else
ptMersenneTwister = new MTRand();
}
et dans le main :
int seed = 1234;
RandomNumGenerator RandomNumGenerator(seed);
et de temps en temps des :
RandomNumGenerator::rand() pour avoir un nombre tiré aléatoirement.
Bien sur le programme plante de temps en temps, personne ne sait
pourquoi. J'ai besoin de savoir si ce genre de pratique (qui est
utilisé largement dans le code avec d'autres class) peut causer des
problemes. Merci de me soutenir et de pas me renvoyer dans mes
pennates en me disant simplement qu'on écrit pas du code comme ça :-)
AG. |
|
| Back to top |
|
 |
Sylvain Guest
|
Posted: Thu May 10, 2007 3:04 pm Post subject: Re: Variable non nommée |
|
|
AG wrote on 10/05/2007 09:29:
| Quote: | je vous dévoile une partie du code :
class MTRand;
class RandomNumGenerator
{
static MTRand* ptMersenneTwister;
|
cette instance (le fournisseur concret de random) n'a aucune raison
d'être static, une variable d'instance privée serait plus adéquate.
| Quote: | static int StartSeed;
|
il ne semble y voir aucun intérêt à stocker la graine initiale - cela
pourrait être utile uniquement s'il existait une méthode "reset" ou si
la méthode Init sans paramètre utilisait cette graine (la dernière
graine transmisse) or elle utilise zéro par défaut.
| Quote: | public:
RandomNumGenerator();
RandomNumGenerator(int seed);
|
vu le code, la définition "RandomNumGenerator(int seed = 0);" aurait été
préférable.
| Quote: | ~RandomNumGenerator();
static void Init();
static void Init(int seed);
|
vu le code, la définition "Init(int seed = 0);" aurait été préférable.
les méthodes devraient être non statiques.
| Quote: | static double rand();
|
la méthode n'a pas d'intérêt à être statique.
le défaut majeur d'avoir ces méthodes statiques et un fournisseur
MTRand* static est évidemment qu'une modification / un appel quelconque
impacte globalement le fournisseur d'aléa; on préférera sûrement pouvoir
disposer de plusieurs instances indépendantes.
en utilisant une (quasi) facade avec un provider interne, on pourrait
préférer:
// déclaration publique
class Randomizer {
private:
Randomizer(const Randomizer&);
protected:
Randomizer() {}
public:
~Randomizer() {}
virtual void init(long seed) {} /* no default initialisation */
virtual void reset() {} /* reset to initial state */
// to be provided by actual implementation
virtual double rand() = 0;
};
class RandomGenerator {
private:
Randomizer* randomizer;
long defaultSeed;
public:
RandomGenerator(long algo, long seed = 0L);
~RandomGenerator();
bool init(long algo, long seed);
void reset();
double rand();
};
// declaration privée et implémentation
// Pseudo-random generator as per MT19937 (Mersenne Twister)
class MTRandom : public Randomizer {
private:
// internal state
// ...
public:
MTRandom();
~MTRandom();
void init(long seed);
void reset();
double rand();
};
// public facade
RandomGenerator::RandomGenerator(long algo, long seed)
{
randomizer = 0;
init(algo, seed);
}
RandomGenerator::~RandomGenerator()
{
if (randomizer)
delete randomizer;
}
bool RandomGenerator::init(long algo, long seed)
{
if (randomizer)
delete randomizer, randomizer = 0;
switch (algo){
case 'MT ':
randomizer = new MTRandom();
break;
// case 'FIPS':
// randomizer = new FipsRandom();
// break;
}
if (randomizer){
randomizer->init(defaultSeed = seed);
return true;
}
return false;
}
void RandomGenerator::reset()
{
if (randomizer)
randomizer->reset();
}
double RandomGenerator::rand()
{
return (randomizer) ? randomizer->rand() : 0.0;
}
RandomGenerator generator('MT ', 1234);
double d = generator.rand();
Sylvain. |
|
| Back to top |
|
 |
Michael DOUBEZ Guest
|
Posted: Thu May 10, 2007 3:36 pm Post subject: Re: Variable non nommée |
|
|
Sylvain a écrit :
| Quote: | AG wrote on 10/05/2007 09:29:
je vous dévoile une partie du code :
[code]
le défaut majeur d'avoir ces méthodes statiques et un fournisseur
MTRand* static est évidemment qu'une modification / un appel quelconque
impacte globalement le fournisseur d'aléa; on préférera sûrement pouvoir
disposer de plusieurs instances indépendantes.
|
C'est pas sûr, plus on utilise un générateur de nombres aléatoire entre
plusieurs modules, plus les nombres sont décorrélés (pour un module, ça
correspond à un sampling de la sortie du générateur). Un des meilleur
système que j'ai utilisé était un processus en arrière plan qui générait
des nombre continuellement et de lui en demander un quand on en avait
besoin.
Un des intérêts d'avoir une classe de nombre aléatoire est
éventuellement d'en utiliser plusieurs instances initialisés à des seeds
différents pour généré des nombres en les combinant. Ca augmente la
cyclicité du générateur global tout en diminuant la prédictibilité.
Un autre est de fournir la reproductibilité des résultats en cas
d'utilisation multithread en utilisant une instance par thread.
Michael |
|
| Back to top |
|
 |
Sylvain Guest
|
Posted: Thu May 10, 2007 3:45 pm Post subject: Re: Variable non nommée |
|
|
Michael DOUBEZ wrote on 10/05/2007 12:36:
| Quote: |
C'est pas sûr, plus on utilise un générateur de nombres aléatoire entre
plusieurs modules, plus les nombres sont décorrélés (pour un module, ça
correspond à un sampling de la sortie du générateur). Un des meilleur
système que j'ai utilisé était un processus en arrière plan qui générait
des nombre continuellement et de lui en demander un quand on en avait
besoin.
|
tous les algos un tant soit peu sérieux que je connaisse dispose d'un
pool - calculé en arrière plan ou quand c'est nécessaire (ie quand vide)
- MT19937 utilise un pool de 624 int32 par exemple; pour autant générer
des nombres en continu n'a pas d'intérêt / sens particulier, et la
qualité de la distribution n'est nullement liée à la taille de ce pool,
une implémentation certifiable FIPS basée sur DES aura par exemple un
pool de 20 octets.
| Quote: | Un des intérêts d'avoir une classe de nombre aléatoire est
éventuellement d'en utiliser plusieurs instances initialisés à des seeds
différents pour généré des nombres en les combinant. Ca augmente la
cyclicité du générateur global tout en diminuant la prédictibilité.
|
je pense plutôt que la qualité de la distribution est inhérente à l'algo
seul, penser améliorer quelque chose en "combinant" a posteriori est
souvent une erreur motivée par le patch sur le patch qui corrigerait
tout (en fait rien).
| Quote: | Un autre est de fournir la reproductibilité des résultats en cas
d'utilisation multithread en utilisant une instance par thread.
|
ces arguments allant donc dans le sens de déclarations d'instances, non
statiques, je ne suis pas sur de comprendre le "c'est pas sur" initial.
Sylvain. |
|
| Back to top |
|
 |
AG Guest
|
Posted: Thu May 10, 2007 6:52 pm Post subject: Re: Variable non nommée |
|
|
Merci à tous pour vos réponses.
Je comprends qu'il s'agit donc bien de code mal écrit, et que nommer
la variable avec le même nom que celui de la classe est une mauvaise
pratique, qui ne sert à rien sinon à brouiller les pistes. Je note
aussi que c'est autorisé par la norme, et que ça ne risque pas de
casser le code (comportement indéfini, etc...).
Je m'en vais batailler contre cette pratique. Merci pour la solution
du singleton, idiome que je ne connaissait pas (encore).
Alexandre. |
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Thu May 10, 2007 6:57 pm Post subject: Re: Variable non nommée |
|
|
On Thu, 10 May 2007 15:52:44 +0200, "AG" <ag (AT) tb (DOT) fr>:
| Quote: | Je comprends qu'il s'agit donc bien de code mal écrit, et que nommer
la variable avec le même nom que celui de la classe est une mauvaise
pratique, qui ne sert à rien sinon à brouiller les pistes.
|
Un autre truc qui est également très douteux : utiliser un
constructeur pour initialiser uniquement des variables statiques.
| Quote: | Je note
aussi que c'est autorisé par la norme, et que ça ne risque pas de
casser le code (comportement indéfini, etc...).
|
Que se passe-t-il si on fait ceci ?
A A (42);
A b (84); |
|
| Back to top |
|
 |
AG Guest
|
Posted: Thu May 10, 2007 7:02 pm Post subject: Re: Variable non nommée |
|
|
| Quote: | Que se passe-t-il si on fait ceci ?
A A (42);
A b (84);
|
Certes |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|