Bonjour,
Je souhaiterais créer une classe Toto et pouvoir l'utiliser de cette facon: Toto::moninstance(param).
Je ne sais plus comment s'appele ce mode d'utilisation d'une classe.
Quelqu'un pourrait-il me rafraichir la mémoire?
D'avance merci.
Bonjour,
Je souhaiterais créer une classe Toto et pouvoir l'utiliser de cette facon: Toto::moninstance(param).
Je ne sais plus comment s'appele ce mode d'utilisation d'une classe.
Quelqu'un pourrait-il me rafraichir la mémoire?
D'avance merci.
Tu veux parler d'une méthode statique?
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Comme l'a dit Medinoc, c'est une methode static. Cependant il est relativement rare de s'en servir comme ca s'il n'y a pas un but particulier. Par-exemple, on pourrait tres bien tomber sur une classe gerant un personnage :
Apres rien ne t'empeche de creer une classe Wizard et une classe Warrior qui heriteront toutes les deux de Perso. Cependant, les methodes statiques me semblent assez peu adaptees a ce genre de cas. J'ai pour habitude de plutot m'en servir lorsque je ne veux qu'une seule instance d'un objet (on appelle ca un singleton au cas ou ce serait ce que tu cherches). Du coup son constructeur est private et le seul moyen de le creer est de passer par une methode statique :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 class Perso { public: static Wizard create_wizard(); static Warrior create_warrior(); }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 class Object { public: static Object *get_instance() { static Object *o(0); if (!o) { o = new Object; } return o; } private: Object(); }
Alors attention à la version du singleton d'imperio, car elle crée une fuite de mémoire, la manière propre de créer un singleton est comme ceci :
version avec référence :
version avec pointeur :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 class Object { public: static Object & get_instance() { static Object instance; return instance; } private: Object(); }
Les deux versions sont équivalentes.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 class Object { public: static Object * get_instance() { static Object instance; return &instance; } private: Object(); }
Avec un pointeur effectivement, ça va "fuiter" mais à la fermeture du programme la mémoire va être libérée.
Sans pointeur, l'objet est détruit et la mémoire libérée mais cela se fait à la fin du programme ...
Donc la "fuite de mémoire" on s'en fout un peu dans ce cas là, que l'on alloue dynamiquement ou pas la zone de mémoire est libérée à la fin.
Par contre, si le destructeur doit faire autre chose que libérer des ressources, là ça devient important, et c'est là que la version "sans pointeur" est plus safe et adaptée.
Le standard garantit-il que la variable locale static est construite lors du premier appel à la fonction, et pas avant?
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Ton OS va libérer la mémoire à la fin mais il n'empêche que ça reste une fuite de mémoire, pour ma part au boulot, on a une politique zero memory leak (on livre des lib), et c'est typiquement le cas où je ne pouvais pas me permettre d'avoir un memory leak.
De toute façon il est meilleur de créer un singleton de cette façon, ça évitera beaucoup de problèmes, et c'est une bonne pratique à prendre.
Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.
L'exemple que j'ai fourni etait quelque chose de simplifie, rien n'empeche de faire appel a atexit pour bien nettoyer la memoire (ou autre methode). Cependant il est vrai qu'il est plus simple de ne pas s'encombrer d'un pointeur et ca a en plus l'avantage d'appeler le destructeur automatiquement.
Petite précision : ce n'est pas parce qu'on veut utiliser static, qu'on veut faire un singleton... (même si le nom de la fonction semble suggérer ça).
Dans ce contexte, static permettra d'indiquer que la fonction moninstance dépendra de la classe et pas d'un objet de la classe.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 class toto { public: static void moninstance() { std::cout << "toto::moninstance()" << std::endl; } };
static a une autre utilité qu'il faut utiliser avec précaution car il s'agit plus ou moins d'une variable globale :
Code : Sélectionner tout - Visualiser dans une fenêtre à part toto::moninstance();
Une fois c'est deux utilisations combinées, on peut faire quelque chose qui s'apparente à un singleton.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++98 -pedantic -fopenmp main.cpp -o main && ./main #include <iostream> #include <string> void f() { static int i = 0; ++i; std::cout << i << std::endl; } int main() { f(); // 1 f(); // 2 f(); // 3 return 0; }
Pour le singleton, la première solution de Danny-k est la plus adaptée en C++11.
Je suis d'accord, il faut toujours faire en sorte qu'il n'y ait jamais de memory leak, ne serait-ce que pour des raisons de concepts ou de sécurité.
Mais dans ce cas là en particulier, techniquement, ça ne change pas grand-chose, sauf si comme je l'ai dit le destructeur de la classe fait autre chose que libérer des ressources.
black_hole, ton but est d'avoir une seule instance de la classe dans tout le programme, ou de pouvoir construire une quantité indéfinie d'objets via une méthode statique ?
Partager