Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

Конструктор A (static | anything) предполагает, что что-то построено - и классы С++ не построены, они просто есть.

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

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

IMO просто не нужно использовать еще один синтаксический способ сделать это.

Ответ 3

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

Как только вы учтете тот факт, что статика должна быть помещена в один (и только один) 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 что-либо).

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

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

Ответ 4

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

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

Ответ 5

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

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

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