Этот оператор определяет статический объект по имени interestRate, который является членом класса Account и имеет тип double. Подобно другим членам класса, определение статического находится в области видимости того класса, где определено его имя. В результате статическую функцию-член initRate() можно использовать для инициализации переменной rate непосредственно, без уточнения класса. Обратите внимание: несмотря на то, что функция-член initRate() является закрытой, ее можно использовать для инициализации объекта interestRate. Определение переменной-члена interestRate, подобно любому другому определению, находится в области видимости класса, а следовательно, имеет доступ к закрытым членам класса.
Обычно статические переменные-члены не могут быть инициализированы в теле класса. Но можно предоставить внутриклассовые инициализаторы для тех статических переменных-членов, которые имеют тип целочисленных констант, или статических членов constexpr литерального типа (см. раздел 7.5.6). Инициализаторы должны быть константными выражениями. Такие члены сами являются константными выражениями; они могут быть использованы там, где ожидается константное выражение. Например, инициализированную статическую переменную-член можно использовать для определения размерности члена типа массива:
class Account {
public:
static double rate() { return interestRate; }
static void rate(double);
private:
static constexpr int period = 30; //
double daily_tbl[period];
};
Если член класса используется только в контекстах, где компилятор может подставить его значение, то инициализированная константа или статическое константное выражение не следует определять отдельно. Но если член класса используется в контексте, где значение не может быть подставлено, то определение для этого члена необходимо.
Например, если переменная period используется только для определения размерности массива daily_tbl, нет никакой необходимости определять ее за пределами класса Account. Но если пропустить определение, то даже, казалось бы, тривиальное изменение в программе может привести к отказу компиляции. Например, если передать переменную-член Account::period функции, получающей параметр типа const int&, то переменную period следует определить.
Если инициализатор предоставляется в классе, определение члена класса не должно задавать исходного значения:
//
constexpr int Account::period; //
//
Как уже упоминалось, статические члены существуют независимо от конкретного объекта. В результате они применимы такими способами, которые недопустимы для нестатических переменных-членов. Например, у статической переменной-члена может быть незавершенный тип (см. раздел 7.3.3). В частности, статическая переменная-член может иметь тип, совпадающий с типом класса, членом которого она является. Нестатическая переменная-член может быть только указателем или ссылкой на объект собственного класса:
class Bar {
public:
// ...
private:
static Bar mem1; //
//
Bar *mem2; //
Bar mem3; //
//
};
Еще одно различие между статическими и обычными членами в том, что статический член можно использовать как аргумент по умолчанию (см. раздел 6.5.1):
class Screen {
public:
//
//
Screen& clear(char = bkground);
private:
static const char bkground;
};