Может кто-нибудь дать техническое объяснение, почему нельзя инициализировать статические переменные внутри класса, а в функциях можно?
Да, я знаю про const static
и инициализацию static
вне класса, но меня интересует техническое объяснение этого процесса.
class A
{
public:
static int a = 10; // нельзя
};
int main()
{
static int b = 10; // можно
}
Это существенно разные вещи с точки зрения языка. В первом случае вы имеете просто объявление статического члена класса с внешним связыванием (external linkage), а во втором - определение статической переменной вообще без связывания (no linkage).
Традиционно в С++ определение сущностей c (для которых требуются определения) - это задача пользователя. И инициализатор традиционно (за редкими исключениями) указывается именно в определении.
Причина этого заключается в том, что выбор единицы трансляции, в которой будет располагаться определение c внешним связыванием в классическом С++ - это часть пользовательского замысла. Т.е. пользователь выбирает, в какой объектный файл попадет это определение.
Также точное место расположения определения статического члена класса определяет его порядок инициализации (и деструкции) в рамках одной единицы трансляции. Это, с точки зрения компилятора, тоже часть пользовательского замысла.
Поэтому компилятор ждет этого решения от вас, а не пытается принимать его сам.
В С++17 появятся inline-переменные, т.е. фактически возможность при помощи ключевого слова inline
сказать компилятору о том, что вас не интересует, где именно будет определен ваш статический член класса. Вот пользуясь эти синтаксисом вы и сможете наконец обойтись без явного указания места определения статического члена и, как следствие, также сможете указывать инициализатор прямо в определении класса
class a
{
public:
static inline int a = 10;
};
Внутри определения класса статические члены класса лишь объявляются, а не определяются. Поэтому внутри объявления класса статические члены класса могут иметь неполный тип. Например,
#include <iostream>
struct A
{
static int a[];
};
int A::a[10];
int main()
{
return 0;
}
В этой демонстрационной программе в определении класса A
объявляется статический член класса - массив a
, который имеет неполный тип, то есть количество элементов массива не задано.
Имейте в виду, что объявление класса может быть включено во множество единиц трансляции, в то время как определение объекта, включая статические члены класса, должно быть только в одной единице трансляции, если только объект не имеет внутреннее связывание.
Кроме того инициализация статических объектов зависит от того, как он расположен относительно других статических объектов. Например, если инициализация некоторого статического объекта зависит от значения другого объекта, то этот статический объект должен быть расположен после того объекта, от которого его инициализация зависит.
В функциях вы имеете дело с определениями объектов, если только они не объявлены со спецификатором extern
. Но в последнем случае они не могут иметь инициализаторов. А в определениях классов вы имеете дело с объявлениями статических членов, а не с их определениями как объектов. С константными статическими членами классов проблем нет, так как они инициализируются констатными значениями, которые вычисляются на этапе компиляции.
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
radstudio c++builder; разработка под андроид;
В БД Oracle хранятся данные в которых присутствует кириллица, CHARACTERSET CL8MSWIN1251Забираю посредством ODBC, вместо кириллицы - знаки вопроса
Есть таблица stuff_id с полями id и nameЕсть таблица stuff_phone с полями id, phone, preference