2010-04-14 6 views
0

Je comprends que le code ci-dessous entraînerait une erreur de segmentation car au niveau de la chaîne cstr de A, B :: SYMBOL n'a pas encore été initialisé. Mais pourquoi?Récupération de valeurs de variables const statiques sur un constructeur d'une variable statique

En réalité, A est un objet qui sert de carte qui mappe les SYMBOL des classes comme B à leurs ID respectifs. C maintient cette carte (A) de manière statique de sorte qu'elle peut fournir le mappage en tant que fonction de classe.

La fonction principale de A est de servir de carte pour C qui s'initialise au démarrage. Comment dois-je être capable de le faire sans faute de segmentation, à condition que je puisse toujours utiliser B :: ID et B :: SYMBOL dans le code (pas #define pls)?

(ps. Suppose que je l'ai mis en œuvre les gardes comprennent)

//A.h 
    #include "B.h" 
    class A 
    { 
    public: 
     A() 
     { 
     std::cout<<B::ID<<std::endl; 
     std::cout<<B::SYMBOL<<std::endl; 
     } 
    }; 

//B.h  
    class B 
    { 
    public: 
     static const int ID; 
     static const std::string SYMBOL; 
    } 

//B.cpp  
    #include "B.h" 
    const int B::ID = 1; 
    const std::string B::SYMBOL = "B"; 

//C.h  
    #include "A.h" 
    class C 
    { 
    public: 
     static A s_A; 
    }; 

//C.cpp  
    #include "C.h" 
    A C::s_A; 

//main.cpp  
    #include "C.h" 
    int main(int c, char** p) 
    { 
    } 

Répondre

1

Utiliser l'initialisation paresseuse de s_a. Cela pourrait fonctionner:

class C 
{ 
public: 
    static A& getA() { static A s_A; return s_A; } 
}; 

Ou:

class C 
{ 
public: 
    static A& getA() 
    { 
    if(ps_A == NULL) ps_A = new ps_A; 
    return *ps_A; 
    } 
private: 
    static A* ps_A; 
}; 

A* C::ps_A = NULL; 

Aucune solution est thread-safe.

1

De quelle faute de segmentation parlez-vous? Votre code ne compilera tout simplement pas, car les membres de B (et B lui-même) ne sont pas déclarés avant A::A(). Le compilateur ne saura simplement pas ce que B est.

Si vous échangez les définitions de A et B, le code doit compiler et fonctionner correctement. Tant que tout est dans la même unité de traduction, il ne devrait y avoir aucun problème avec l'ordre d'initialisation, en supposant que les définitions des membres statiques de B précèdent la définition de C::s_A. Les objets définis dans la même unité de traduction sont initialisés dans l'ordre de leur définition, ce qui signifie qu'au moment où commence A::A(), les membres statiques de B sont déjà initialisés. Il n'y a pas de potentiel pour la faute de segmentation dans ce cas comme présenté.

Si vous obtenez une erreur de segmentation, vous devez faire quelque chose différemment. L'ordre de définition est différent? Plusieurs unités de traduction peut-être? Poster/décrire le code réel.

+0

Dans mon code, je les mets dans des fichiers d'en-tête et les inclut correctement. Donc, ils ne sont pas dans la même unité de traduction parce qu'ils sont réellement écrits dans des fichiers différents. – gilbertc

+0

@gilbertc: Eh bien, avec l'initialisation des globals et des statiques, qu'ils soient dans le même TU fait une différence. Donc vous feriez mieux d'adapter votre exemple à quelque chose qui reproduit le problème. – sbi

+0

@sbi: merci. édité. – gilbertc