В чем причина отсутствия статического конструктора в C ++? - PullRequest
29 голосов
/ 14 марта 2011

В чем причина отсутствия статического конструктора в C ++?

Если бы это было разрешено, мы бы инициализировали все статические элементы в нем, в одном месте, очень организованно, как:

//illegal C++
class sample
{
public:

    static int some_integer;
    static std::vector<std::string> strings;

    //illegal constructor!
    static sample()
    {
       some_integer = 100;
       strings.push_back("stack");
       strings.push_back("overflow");
    }
};

В отсутствие статического конструктора очень сложно иметь статический вектор и заполнять его значениями, как показано выше. Статический конструктор элегантно решает эту проблему. Мы могли бы инициализировать статические члены очень организованно.

Так почему же в C ++ нет статического конструктора? В конце концов, другие языки (например, C #) имеют статический конструктор!

Ответы [ 5 ]

20 голосов
/ 14 марта 2011

Использование проблемы статического порядка инициализации в качестве предлога для того, чтобы не вводить эту функцию в язык, является и всегда было вопросом статус-кво - оно не было введено, потому что оно не было введено, и люди продолжают думать, что порядок инициализации былпричина не вводить его, даже если проблема заказа имеет простое и очень простое решение.

Порядок инициализации, если бы люди действительно хотели бы решить проблему, у них было бы очень простое и прямое решение:

//called before main()

int static_main() {

ClassFoo();
ClassBar();

}

с соответствующими декларациями:

class ClassFoo {
 static int y;
  ClassFoo() {
   y = 1;
  }
}

class ClassBar {
  static int x;
  ClassBar() {
   x = ClassFoo::y+1;
  }
}

Таким образом, ответ таков: причины нет, по крайней мере, не техническая.

13 голосов
/ 14 марта 2011

Это на самом деле не имеет смысла для c ++ - классы не являются объектами первого класса (как, например, в java).

Конструктор (статический | что угодно) подразумевает, что что-то создано - а классы c ++ не созданы, они просто есть.

Вы можете легко добиться того же эффекта, хотя:

//.h
struct Foo {
  static std::vector<std::string> strings;
};
//.cpp
std::vector<std::string> Foo::strings(createStrings());

IMO, просто нет необходимости в еще одном синтаксическом способе сделать это.

6 голосов
/ 14 марта 2011

В какую единицу перевода будут помещены статические объекты?

Как только вы учли тот факт, что статика должна быть размещена в одном (и только одном) ТУ, переходить на нее не очень сложно.до конца и присвойте им значения в функции:

// .h
class sample
{
public:
    static int some_integer;
    static std::vector<std::string> strings;
};

//.cpp

// we'd need this anyway
int sample::some_integer;
std::vector<std::string> sample::strings;

// add this for complex setup
struct sample_init {
    sample_init() {
       sample::some_integer = 100;
       sample::strings.push_back("stack");
       sample::strings.push_back("overflow");
    }
} x;

Если вы действительно хотите, чтобы код для sample_init появился в определении класса sample, то вы могли бы даже поместитьэто там как вложенный класс.Вам просто нужно определить его экземпляр в том же месте, где вы определяете статику (и после они были инициализированы через свои конструкторы по умолчанию, в противном случае, конечно, вы не можете push_back ничего).

C # был изобретен через 15-20 лет после C ++ и имеет совершенно другую модель сборки.Неудивительно, что он предлагает различные функции и некоторые вещи в C ++ менее просты, чем в C #.

C ++ 0x добавляет функции, упрощающие инициализацию векторов с некоторыми данными, называемыми "списки инициализаторов "

4 голосов
/ 14 марта 2011

Вы можете обойтись, поместив свои "статические" члены в их собственный класс с их собственным конструктором, который выполняет их инициализацию:

class StaticData
{
    int some_integer;
    std::vector<std::string> strings;

public:
    StaticData()
    {
       some_integer = 100;
       strings.push_back("stack");
       strings.push_back("overflow");
    }
}

class sample
{    
    static StaticData data;

public:
    sample()
    {

    }
};

Ваш статический data член гарантированно будет инициализирован перед первымпопробуйте получить к нему доступ.(Возможно, до основного, но не обязательно)

2 голосов
/ 14 марта 2011

Статика подразумевает функцию, которая не связана с объектом.Поскольку создаются только объекты, неясно, почему статический конструктор принесет какую-либо пользу.

Вы всегда можете держать объект в статической области видимости, которая была построена в статическом блоке, но конструктор, который вы бы использоваливсе равно будет объявлен нестатичным.Нет правила, указывающего на то, что нельзя вызывать нестатический метод из статической области.

Наконец, C ++ / C определяет начало программы при входе в функцию main.Статические блоки вызываются до ввода функции main как часть настройки «среды» оцениваемого кода.Если ваша среда требует полного контроля над настройкой и демонтажем, то легко утверждать, что на самом деле это не какое-то приспособление к окружающей среде, а наследственный процедурный компонент программы.Я знаю, что последний бит является своего рода философией кода (и что ее обоснование можно интерпретировать по-разному), но не следует помещать критический код «до» официального запуска исполняемого файла, передающего «полный контроль» написанному коду.программистом.

...