Quelle est la raison pour ne pas avoir de constructeur statique en C ++?
Si cela était autorisé, nous initialiserions tous les membres statiques qui s’y trouvent, à un endroit de manière très organisée, comme suit:
//illegal C++ class sample { public: static int some_integer; static std::vector ssortingngs; //illegal constructor! static sample() { some_integer = 100; ssortingngs.push_back("stack"); ssortingngs.push_back("overflow"); } };
En l’absence de constructeur statique, il est très difficile d’avoir un vecteur statique et de le renseigner avec des valeurs, comme indiqué ci-dessus. Le constructeur statique résout élégamment ce problème. Nous pourrions initialiser les membres statiques de manière très organisée.
Alors, pourquoi le C ++ n’a-t-il pas de constructeur statique? Après tout, d’autres langages (par exemple, C #) ont un constructeur statique!
Utiliser le problème de l’ordre d’initialisation statique comme excuse pour ne pas introduire cette fonctionnalité dans la langue est et a toujours été une affaire de statu quo – elle n’a pas été introduite car elle n’a pas été introduite et les gens continuent de penser que l’ordre d’initialisation était une raison valable pour l’introduire, même si le problème d’ordre a une solution simple et très simple.
L’ordre d’initialisation, si les gens avaient vraiment voulu s’attaquer au problème, ils auraient eu une solution très simple et directe:
//called before main() int static_main() { ClassFoo(); ClassBar(); }
avec les déclarations appropriées:
class ClassFoo { static int y; ClassFoo() { y = 1; } } class ClassBar { static int x; ClassBar() { x = ClassFoo::y+1; } }
La réponse est donc qu’il n’y a aucune raison qu’il ne soit pas là, du moins pas technique.
Cela n’a pas vraiment de sens pour c ++ – les classes ne sont pas des objects de première classe (comme dans java, par exemple).
Un constructeur (statique | n’importe quoi) implique que quelque chose soit construit – et que les classes c ++ ne sont pas construites, elles le sont tout simplement.
Vous pouvez facilement obtenir le même effet si:
//.h struct Foo { static std::vector ssortingngs; }; //.cpp std::vector Foo::ssortingngs(createSsortingngs());
OMI, il n’y a pas besoin d’une autre façon syntaxique de le faire.
Dans quelle unité de traduction les objects statiques seraient-ils placés?
Une fois que vous avez pris en compte le fait que la statique doit être placée dans une (et une seule) TU, il n’est alors pas “très difficile” de faire le rest du chemin et de leur atsortingbuer des valeurs dans une fonction:
// .h class sample { public: static int some_integer; static std::vector ssortingngs; }; //.cpp // we'd need this anyway int sample::some_integer; std::vector sample::ssortingngs; // add this for complex setup struct sample_init { sample_init() { sample::some_integer = 100; sample::ssortingngs.push_back("stack"); sample::ssortingngs.push_back("overflow"); } } x;
Si vous voulez vraiment que le code de sample_init
apparaisse dans la définition de la classe sample
, vous pouvez même le mettre là comme une classe nestede. Il vous suffit de définir l’instance de celle-ci au même endroit que vous définissez les statiques (et après leur initialisation via leurs constructeurs par défaut, sinon vous ne pouvez bien sûr pas tout push_back
).
C # a été inventé 15 à 20 ans après C ++ et possède un modèle de construction complètement différent. Il n’est pas étonnant qu’il offre différentes fonctionnalités et que certaines choses soient moins simples en C ++ qu’en C #.
C ++ 0x ajoute une fonctionnalité facilitant l’initialisation des vecteurs avec certaines données, appelées “listes d’initialisation”
Vous pouvez vous débrouiller en plaçant vos membres “statiques” dans leur propre classe avec leur propre constructeur qui effectue leur initialisation:
class StaticData { int some_integer; std::vector ssortingngs; public: StaticData() { some_integer = 100; ssortingngs.push_back("stack"); ssortingngs.push_back("overflow"); } } class sample { static StaticData data; public: sample() { } };
Il est garanti que votre membre de data
statique est initialisé avant d’essayer d’y accéder pour la première fois. (Probablement avant mais pas nécessairement)
Statique implique une fonction dissociée d’un object. Etant donné que seuls les objects sont construits, on ne voit pas pourquoi un constructeur statique aurait un quelconque avantage.
Vous pouvez toujours contenir un object dans une scope statique construite dans un bloc statique, mais le constructeur que vous utiliseriez serait toujours déclaré non statique. Aucune règle n’indique que vous ne pouvez pas appeler une méthode non statique à partir d’une scope statique.
Enfin, C ++ / C définit le début d’un programme lorsque la fonction main
est entrée. Les blocs statiques sont appelés avant la saisie de la fonction main
dans le cadre de la configuration de “l’environnement” du code évalué. Si votre environnement impose un contrôle total sur la configuration et le démantèlement, il est alors facile d’affirmer qu’il ne s’agit pas vraiment d’un élément environnemental, mais d’un élément de procédure hérité du programme. Je sais que le dernier bit est une sorte de philosophie du code (et que sa raison peut être interprétée différemment), mais il ne faut pas mettre de code critique “avant” le début officiel du passage d’un exécutable à un “contrôle total” du code écrit par le programmeur.