views:

197

answers:

2

I understand that the code below would result segmentation fault because at the cstr of A, B::SYMBOL was not initialized yet. But why?

In reality, A is an object that serves as a map that maps the SYMBOLs of classes like B to their respective IDs. C holds this map(A) static-ly such that it can provide the mapping as a class function.

The primary function of A is to serve as a map for C that initializes itself at startup. How should I be able to do that without segmentation fault, provided that I can still use B::ID and B::SYMBOL in the code (no #define pls)?

(ps. assume I have implemented the include guards)

//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)
    {
    }
+1  A: 

Use lazy initialization of s_A. This might work:

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

Or:

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;

Neither solution is thread safe.

Cătălin Pitiș
+1  A: 

What segmentation fault are you talking about? Your code simply will not compile, because members of B (and B itself) are not declared before A::A(). The compiler simply will not know what B is.

If you exchange the definitions of A and B, then the code should compile and work fine. As as long as everything is in the same translation unit, there shouldn't be any problems with the initialization order, assuming that the definitions of static members of B precede the definition of C::s_A. Objects defined in the same translation unit are initialized in the order of their definition, meaning that by the time A::A() starts, static members of B are already initialized. There's no potential for the segmentation fault in this case as presented.

If you are getting a segmentation fault, you must be doing something differently. Order of definition is different? Multiple translation units maybe? Post/describe the real code.

AndreyT
In my code I put them into header files and do the includes correctly. So, they are not in the same translation unit coz they are actually written in different files.
gilbertc
@gilbertc: Well, with initialization of globals and statics, whether they are in the same TU does make a difference. So you better adapt your example to something that actually reproduces the problem.
sbi
@sbi: thanks. edited.
gilbertc