Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Variable locale "presque static"

13 réponses
Avatar
Fabien LE LEZ
Bonjour,

Supposons que dans une fonction f(), j'aie besoin d'une variable
locale qui garde sa valeur d'un appel à l'autre.
Il y a une solution simple, propre et élégante : la déclarer "static".

// x.h

void f();


// x.cpp

void f()
{
static unsigned int nb_appels= 0;
cout << "La fonction f() a été appelée "
<< (++nb_appels) << " fois \n";
}


La variable "nb_appels" est un détail d'implémentation, on n'en parle
pas du tout dans le .h, tout va bien.



Supposons maintenant que f() soit membre d'une classe C, et que j'aie
besoin d'une variable locale, qui garde sa valeur à d'un appel à
l'autre, mais spécifique à chaque instance de C.
Avec bien sûr le même cahier des charges que précédemment :
- la variable doit être locale à la fonction, ou au moins
invisible par les autres fonctions ;
- on doit pouvoir ajouter une telle variable sans modifier le .h
(i.e. la définition de la classe) ; idéalement, on ne devrait en
parler nulle part en-dehors de la définition de C::f().


Et là, je coince.
Il y a bien la solution bâtarde de mettre cette variable comme membre
de C, mais alors il faut la déclarer dans le .h, éventuellement
l'initialiser dans le constructeur de C, et elle est loin d'être
locale à C::f().

Une autre solution serait de transformer f() en un foncteur, i.e. un
objet qui contient cette variable et un operateur "()".
Au moins, la variable est inaccessible à autre chose que f(), mais ça
change profondément la définition de C.


Si quelqu'un a une idée pour résoudre élégamment ce problème...
Merci d'avance !

3 réponses

1 2
Avatar
kanze
Fabien LE LEZ wrote:
On Wed, 19 Apr 2006 22:31:44 +0200, James Kanze :

Le problème avec l'histoire de map, c'est que si le
déstructeur ne libere pas l'instance de ta variable, tu
risques de créer une deuxième instance de l'objet à la même
adresse plus tard, et trouver l'instance de ta variable qui
correspond à l'objet déjà détruit.


Oui. C'est pour ça que j'aimerais autant éviter.


Je comprends bien. Au fond, il ne convient qu'aux classes dont
on ne détruit jamais les instances.

À la rigueur [...] tu appelle la fonction dépuis le
destructeur, avec ce peramètre à true,


Ben oui mais non. Ça suppose autant de modifications que
l'ajout d'une variable membre (quitte à la rendre inaccessible
à d'autres fonctions, cf solution de Joni).


C'est sûrement la solution la plus élégante. Mais tu disais ne
pas vouloir modifier la définition de la classe.

--
James Kanze GABI Software
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


Avatar
Fabien LE LEZ
On 20 Apr 2006 07:56:57 -0700, "kanze" :

Mais tu disais ne
pas vouloir modifier la définition de la classe.


Disons que j'espérais ne rien modifier d'autre que le code de la
fonction -- i.e. faire en sorte que la cuisine interne d'une fonction
(ici, une variable locale) ne se "répande" pas dans tous les coins.

Avatar
Fabien LE LEZ
On Wed, 19 Apr 2006 22:31:44 +0200, James Kanze :

Mon histoire avec std::map fera alors l'affaire. Tu utilises [],
avec l'adresse de l'objet comme indice


L'adresse de l'objet ne convient pas ; par contre, je verrais bien un
système d'identification des objets, de telle sorte que deux objets ne
peuvent jamais avoir le même identifiant, même si l'un a été créé
après la destruction d'un autre, et quelle que soit la classe de
l'objet.

class IdentifiantObjet
{
public:
typedef int Identifiant;
IdentifiantObjet();
operator Identifiant() const { return id; }
private:
Identifiant id;
};

IdentifiantObjet::IdentifiantObjet()
{
static Identifiant id_suivant= 0;
id= id_suivant++;
}

1 2