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

В чем причина отсутствия статического конструктора в 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#) имеют статический конструктор!

6 ответов

Решение

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

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

//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;
  }
}

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

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

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

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

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

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

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

После того, как вы учли тот факт, что статики должны быть размещены в одном (и только одном) TU, тогда не будет "очень сложно" пройти остаток пути и присвоить им значения в функции:

// .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 добавляет функции, упрощающие инициализацию векторов с некоторыми данными, называемые "списки инициализаторов"

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

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 член гарантированно будет инициализирован перед первой попыткой доступа к нему. (Возможно перед основным, но не обязательно)

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

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

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

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

Мы пишем статическую функцию для инициализации статических членов и вызова этой функции. Так. Я думаю, было бы лучше иметь статические конструкторы.

Как инициализировать статические члены класса?.

Другие вопросы по тегам