Страницы

Поиск по вопросам

понедельник, 6 января 2020 г.

Инициализация статического члена в main

#cpp


Как инициализировать неконстантный статический член класса до создания экземпляра
класса в функции main?

Например:

class A
{
protected:
 static int x;
 A(){}
public:
};
class B: public A
{
};

int main()
{
// нужно инициализировать x здесь
B b;
}

    


Ответы

Ответ 1



Добавьте статическую функцию, которая будет присваивать значение x и вызывайте её: class A { protected: static int _x; A() {} public: static void InitX(int x) { _x = x; } }; В main: int main() { A::InitX(5); B b; } Если нужна именно инициализация, то Вы не можете контролировать то, когда она будет выполнена, но она обязательно будет выполнена до main. В Вашем коде, кстати, как раз не хватает инициализации, а без неё код не соберётся. Добавьте в глобальной области видимости следующее: int A::x = 0;

Ответ 2



Статические поля класса всегда инициализируются до вызова функции main. Это связано с тем, что статические поля, по своей сути — это те же глобальные переменные, только с именем в специальном формате. Соответственно, они хранятся в одном и том же месте и одним и тем же способом — будучи «вшитыми» в секцию данных исполняемого файла. Мы выяснили, когда задаётся значение статических полей. Теперь перейдём к тому, как это сделать. Указать значение поля в конструкторе владеющего класса мы не можем — статическое поле мало того что не принадлежит ни к одному экземпляру класса, так ещё и известно до момента запуска стартовой функции. Задать значение в самом объявлении класса мы тоже не можем, так как хранится поле в одном месте, а обращение к нему происходит из многих мест; кто из обращающихся будет отвечать за инициализацию ячейки памяти с переменной? Примечание: по крайней мере так было до C++14, но как это реализовано там — отдельный вопрос. Поэтому как инициализация, так и резервирование статического поля класса производится аналогично таковым для глобальных переменных (ещё один пункт их сходства), а именно путём его упоминания в каком-нибудь .cpp файле. Примерно так: int A::_x; // Значение поля будет определено позднее Или так: int A::_x = 12; // Значение поля «вшито» в исполняемый файл Или даже так: // myStaticFunction — статический метод класса A. // Можно уверенно утверждать, что все указанные в нём // действия выполняются строго до вызова функции main. int A::_x = A::myStaticFunction(); То есть сначала указывается тип поля, затем его полное имя со всеми пространствами имён, и, наконец, то, чем это поле будет инициализировано — константой (точнее, литералом), возвращаемым значением функции или вообще ничем. Остановимся подробнее на втором способе, как наиболее соответствующем требованиям автора вопроса. Инициализация может быть произведена не просто любой функцией (за исключением нестатических методов по понятным причинам), а вообще любым функциональным объектом. Однако, есть одно существенное ограничение. Согласно стандарту, порядок инициализации статических полей достоверно известен только в пределах (упрощая) одного .cpp файла. Как результат, к моменту вызова нашей функции достоверно инициализированы только те поля, которые указаны точно таким же образом, но выше по этому же файлу. Порядок же инициализации полей и переменных из других .cpp файлов зависит от компилятора и порядка перечисления файлов с исходными кодами в проекте. Всё это стоит учитывать при обращении из функции к другим статическим полям и глобальным переменным.

Комментариев нет:

Отправить комментарий