В общем случае статический член инициализируется вне определения класса. Его имя во внешнем определении должно быть специфицировано именем класса. Вот так можно инициализировать _interestRate:
// явная инициализация статического члена класса
#include "account.h"
double Account::_interestRate = 0.0589;
В программе может быть только одно определение статического члена. Это означает, что инициализацию таких членов следует помещать не в заголовочные файлы, а туда, где находятся определения невстроенных функций-членов класса.
В объявлении статического члена можно указать любой тип. Это могут быть константные объекты, массивы, объекты классов и т.д. Например:
#include string
class Account {
// ...
private:
static const string name;
};
const string Account::name( "Savings Account" );
Константный статический член целого типа инициализируется константой внутри тела класса: это особый случай. Если бы для хранения названия счета мы решили использовать массив символов вместо строки, то его размер можно было бы задать с помощью константного члена типа int:
// заголовочный файл
class Account {
//...
private:
static const int nameSize = 16;
static const string name[nameSize];
};
// исходный файл
const string Account::nameSize; // необходимо определение члена
const string Account::name[nameSize] = "Savings Account";
Отметим, что константный статический член целого типа, инициализированный константой, – это константное выражение. Проектировщик может объявить такой статический член, если внутри тела класса возникает необходимость в именованной константе. Например, поскольку константный статический член nameSize является константным выражением, проектировщик использует его для задания размера члена-массива с именем name.
Даже если такой член инициализируется в теле класса, его все равно необходимо задать вне определения класса. Однако поскольку начальное значение уже задано в объявлении, то при определении оно не указывается.
Так как name – это массив (и не целого типа), его нельзя инициализировать в теле класса. Попытка поступить таким образом приведет к ошибке компиляции:
class Account {
//...
private:
static const int nameSize = 16; // правильно: целый тип
static const string name[nameSize] = "Savings Account"; // ошибка
};
Член name должен быть инициализирован вне определения класса.
Обратите внимание, что член nameSize задает размер массива name в определении, находящемся вне тела класса:
const string Account::name[nameSize] = "Savings Account";
nameSize не квалифицирован именем класса Account. И хотя это закрытый член, определение name не приводит к ошибке. Как такое может быть? Определение статического члена аналогично определению функции-члена класса, которое может ссылаться на закрытые члены. Определение статического члена name находится в области видимости класса и может ссылаться на закрытые члены, после того как распознано квалифицированное имя Account::name. (Подробнее об области видимости класса мы поговорим в разделе 13.9.)
Статический член класса доступен функции-члену того же класса и без использования соответствующих операторов:
inline double Account::dailyReturn()
{
return( _interestRate / 365 * _amount );
}
Что же касается функций, не являющихся членами класса, то они могут обращаться к статическому члену двумя способами. Во-первых, посредством операторов доступа:
class Account {
// ...
private:
friend int compareRevenue( Account&, Account* );
// остальное без изменения
};
// мы используем ссылочный и указательный параметры,
// чтобы проиллюстрировать оба оператора доступа
int compareRevenue( Account &ac1, Account *ac2 );
{
double ret1, ret2;
ret1 = ac1._interestRate * ac1._amount;
ret2 = ac2-_interestRate * ac2-_amount;
// ...
}
Как ac1._interestRate, так и ac2-_interestRate относятся к статическому члену Account::_interestRate.