Ключевое слово static
имеет разные значения в C ++, в зависимости от контекста.
Когда объявляется свободная функция или глобальная переменная, это означает, что функция не должна быть доступна вне этой единственной единицы перевода:
// test.cpp
static int a = 1;
static void foo() {}
Если результат компиляции этой единицы перевода связан с другой единицей перевода, содержащей символы a
и foo
, это не нарушит правило единого определения, как в этой конкретной единице перевода a
и foo
приват символов. Это использование было отменено безымянными пространствами имен.
// test2.cpp
namespace {
static int a = 1;
static void foo() {}
}
Когда объявляется локальная переменная внутри функции, это означает, что время жизни переменной будет увеличиваться от первого вызова функции до конца программы, а не только на время вызова:
int foo() {
static int counter = 0;
return ++counter;
}
int main() {
for ( int i = 0; i < 10; ++i ) {
std::cout << foo() << std::endl;
}
}
В предыдущем коде counter
инициализируется один раз, когда foo
вызывается впервые, но переменная переживет функцию и сохранит значение при различных вызовах функций. В предыдущем коде будет напечатано «1 2 3 4 ... 10». Если переменная не была объявлена static
, то результатом будет «1 1 1 ... 1».
В пределах области видимости static
означает, что член является членом класса, а не конкретного экземпляра. Это использование эквивалентно использованию в вашем другом вопросе: использование этого конкретного члена не связано ни с каким конкретным объектом.
struct test {
int x;
static int y;
};
int test::y; // need to define it in one translation unit
int main() {
// test::x = 5; // !error cannot access a non-static member variable
// without an instance
test::y = 5; // ok
test t, other;
t.x = 10; // ok
t.y = 15; // ok, the standard allows calling a static member through
// an instance, but this is the same as test::y
}
В этом случае член x
является нестатическим атрибутом члена, и поэтому для каждого экземпляра класса есть разные x
. В примере программы t.x
и other.x
относятся к разным целым числам. С другой стороны, y
- это static
, и поэтому в программе есть единственный экземпляр test::y
. Даже если стандарт позволяет вызывать t.y
и other.y
, оба использования относятся к одной и той же переменной. То же самое касается методов членов. Если они статические, они являются методами уровня класса и могут вызываться без экземпляра, тогда как если они нестатические, они применяются к конкретному экземпляру, и должен использоваться синтаксис a.b
или a->b
.
Это использование static
аналогично использованию одного и того же ключевого слова в Java, тогда как два других не присутствуют на этом языке. Существует одно использование ключевого слова в Java, которого нет в C ++, и это использование статических инициализаторов классов (блок кода на уровне класса, окруженный static { ... }
). В Java этот блок кода будет выполняться при загрузке класса и только один раз. Инициализация статических переменных-членов в C ++ должна выполняться в инициализаторе определения переменной.