Maison >développement back-end >C++ >Pourquoi `B::getB()` ne parvient-il pas à initialiser `mB` dans les classes modélisées avec des membres statiques ?

Pourquoi `B::getB()` ne parvient-il pas à initialiser `mB` dans les classes modélisées avec des membres statiques ?

Linda Hamilton
Linda Hamiltonoriginal
2024-10-31 05:59:02528parcourir

 Why Does `B::getB()` Fail to Initialize `mB` in Templated Classes with Static Members?

Initialisation des membres statiques dans les modèles : une plongée plus approfondie

En C, l'initialisation des membres statiques pour les structures d'assistance imbriquées fonctionne généralement sans problème pour les classes sans modèle. Cependant, lorsque la classe englobante est modélisée, une bizarrerie potentielle survient si l'objet d'assistance n'est pas accessible dans le code principal.

Le problème avec les classes modélisées

Considérez l'exemple simplifié suivant :

<code class="cpp">struct A
{
    struct InitHelper
    {
        InitHelper()
        {
            A::mA = "Hello, I'm A.";
        }
    };
    static std::string mA;
    static InitHelper mInit;

    static const std::string& getA(){ return mA; }
};

template<class T>
struct B
{
    struct InitHelper
    {
        InitHelper()
        {
            B<T>::mB = "Hello, I'm B.";
        }
    };
    static std::string mB;
    static InitHelper mInit;

    static const std::string& getB() { return mB; }
    static InitHelper& getHelper(){ return mInit; }
};</code>

Ici, InitHelper imbriqué initialise le membre statique mA pour A et mB pour B.

Le problème se pose lorsque nous essayons d'initialiser les membres dans une classe B basée sur un modèle. Utilisation de la méthode getB , comme indiqué ci-dessous, ne déclenche pas l'initialisation de mB :

<code class="cpp">std::cout << "B = " << B<int>::getB() << std::endl;

Cela se produit car, selon la norme ISO/IEC C 2003 (14.7.1), l'initialisation d'un membre de données statique se produit uniquement lorsque le membre est lui-même utilisé d'une manière qui nécessite sa définition. Dans ce cas, puisque mB n'est référencé que dans la méthode getB() de la classe modélisée, le compilateur n'instancie pas implicitement sa définition.

Instanciation implicite et spécialisation explicite

Pour comprendre le compilateur comportement, il est important de clarifier le concept d’instanciation implicite. Pour les données membres statiques dans les modèles, une instanciation implicite instancie les déclarations mais pas les définitions. L'initialisation réelle (appels du constructeur) ne se produit que lorsque le membre de données statique est utilisé d'une manière qui nécessite sa définition (par exemple, affectation).

D'autre part, les spécialisations explicites utilisent des déclarations explicites dans des espaces de noms ou des classes, qui ont ordonné l'initialisation. En d'autres termes, une donnée membre statique spécialisée est toujours initialisée avant toute instanciation de son modèle de classe.

La réponse

Dans votre exemple de code spécifique, en appelant B::getHelper() déclenche l'initialisation de mB et de mInit car getHelper renvoie une référence à mInit, ce qui nécessite l'existence de InitHelper.

Cependant, s'appuyer sur l'ordre d'initialisation est un comportement indéfini. La solution correcte consiste à spécialiser explicitement le membre de données statiques mInit dans la classe B. Cela garantira que l'objet d'assistance est toujours créé et que toute instanciation ultérieure de B verra ses membres de données statiques initialisés correctement.

Conclusion

Pour résumer, l'initialisation des membres statiques dans les modèles C nécessite un examen attentif. L'instanciation implicite instancie uniquement les déclarations, pas les définitions. Pour une initialisation ordonnée et fiable, une spécialisation explicite doit être envisagée lorsqu'il s'agit de classes basées sur un modèle contenant des données membres statiques.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn