Получение значений статических константных переменных у конструктора статической переменной - PullRequest
0 голосов
/ 14 апреля 2010

Я понимаю, что приведенный ниже код приведет к ошибке сегментации, потому что в Cstr A, B :: SYMBOL еще не был инициализирован. Но почему?

В действительности, A - это объект, который служит картой, которая отображает СИМВОЛЫ классов, таких как B, в соответствующие им идентификаторы. C хранит это отображение (A) статично, так что оно может предоставить отображение в виде функции класса.

Основная функция A - служить картой для C, которая инициализируется при запуске. Как мне сделать это без ошибки сегментации, при условии, что я все еще могу использовать B :: ID и B :: SYMBOL в коде (без #define pls)?

(пс. Предположим, я включил охрану включения)

//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)
    {
    }

Ответы [ 2 ]

1 голос
/ 15 апреля 2010

О какой ошибке сегментации вы говорите? Ваш код просто не скомпилируется, потому что члены B (и самого B) не объявлены до A::A(). Компилятор просто не будет знать, что такое B.

Если вы обмениваетесь определениями A и B, то код должен скомпилироваться и работать нормально. Пока все находятся в одной и той же единице перевода, не должно быть никаких проблем с порядком инициализации, предполагая, что определения статических членов B предшествуют определению C::s_A. Объекты, определенные в одной и той же единице перевода, инициализируются в порядке их определения. Это означает, что к моменту запуска A::A() статические члены B уже инициализированы. В этом случае, как показано, нет вероятности ошибки сегментации.

Если вы получаете ошибку сегментации, вы должны делать что-то по-другому. Порядок определения отличается? Может быть, несколько единиц перевода? Разместите / опишите реальный код.

1 голос
/ 15 апреля 2010

Использовать ленивую инициализацию s_A. Это может сработать:

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

Или:

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;

Ни одно из решений не является поточно-ориентированным.

...