// доступ к статическому члену с указанием квалифицированного имени
if ( Account::_interestRate 0.05 )
Если обращение к статическому члену производится без помощи оператора доступа, то его имя следует квалифицировать именем класса, за которым следует оператор разрешения области видимости:
Account::
Это необходимо, поскольку такой член не является глобальным объектом, а значит, в глобальной области видимости отсутствует. Следующее определение дружественной функции compareRevenue эквивалентно приведенному выше:
int compareRevenue( Account &ac1, Account *ac2 );
{
double ret1, ret2;
ret1 = Account::_interestRate * ac1._amount;
ret2 = Account::_interestRate * ac2-_amount;
// ...
}
Уникальная особенность статического члена – то, что он существует независимо от объектов класса, – позволяет использовать его такими способами, которые для нестатических членов недопустимы.
* статический член может принадлежать к типу того же класса, членом которого он является. Нестатические объявляются лишь как указатели или ссылки на объект своего класса:
class Bar {
public:
// ...
private:
static Bar mem1; // правильно
Bar *mem2; // правильно
Bar mem3; // ошибка
};
* статический член может выступать в роли аргумента по умолчанию для функции-члена класса, а для нестатического это запрещено:
extern int var;
class Foo {
private:
int var;
static int stcvar;
public:
// ошибка: трактуется как Foo::var,
// но ассоциированного объекта класса не существует
int mem1( int = var );
// правильно: трактуется как static Foo::stcvar,
// ассоциированный объект и не нужен
int mem2( int = stcvar );
// правильно: трактуется как глобальная переменная var
int mem3( int = :: var );
};
13.5.1. Статические функции-члены
Функции-члены raiseInterest() и interest() обращаются к глобальному статическому члену _interestRate:
class Account {
public:
void raiseInterest( double incr );
double interest() { return _interestRate; }
private:
static double _interestRate;
};
inline void Account::raiseInterest( double incr )
{
_interestRate += incr;
}
Проблема в том, что любая функция-член должна вызываться с помощью оператора доступа к конкретному объекту класса. Поскольку приведенные выше функции обращаются только к статическому _interestRate, то совершенно безразлично, для какого объекта они вызываются. Нестатические члены при вызове этих функций не читаются и не модифицируются.
Поэтому лучше объявить такие функции-члены как статические. Это можно сделать следующим образом:
class Account {
public:
static void raiseInterest( double incr );
static double interest() { return _interestRate; }
private:
static double _interestRate;
};
inline void Account::raiseInterest( double incr )
{
_interestRate += incr;
}
Объявление статической функции-члена почти такое же, как и нестатической: в теле класса ему предшествует ключевое слово static, а спецификаторы const или volatile запрещены. В ее определении, находящемся вне тела класса, слова static быть не должно.
Такой функции-члену указатель this не передается, поэтому явное или неявное обращение к нему внутри ее тела вызывает ошибку компиляции. В частности, попытка обращения к нестатическому члену класса неявно требует наличия указателя this и, следовательно, запрещена. Например, представленную ранее функцию-член dailyReturn() нельзя объявить статической, поскольку она обращается к нестатическому члену _amount.
Статическую функцию-член можно вызвать для объекта класса, пользуясь одним из операторов доступа. Ее также можно вызвать непосредственно, квалифицировав ее имя, даже если никаких объектов класса не объявлено. Вот небольшая программа, иллюстрирующая их применение:
#include iostream
#include "account.h"
bool limitTest( double limit )
{
// пока еще ни одного объекта класса Account не объявлено
// правильно: вызов статической функции-члена
return limit = Account::interest() ;
}
int main() {
double limit = 0.05;
if ( limitTest( limit ) )
{
// указатель на статическую функцию-член
// объявлен как обычный указатель