13.5.1. Статические функции-члены

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 ) )

{

// указатель на статическую функцию-член

// объявлен как обычный указатель

void (*psf)(double) = &Account::raiseInterest;

psf( 0.0025 );

}

Account ac1( 5000, "Asterix" );

Account ac2( 10000, "Obelix" );

if ( compareRevenue( ac1, &ac2 ) & 0 )

cout ac1.owner()

"is richer than "

ac2.owner() " ";

else

cout ac1.owner()

" is poorer than"

ac2.owner() " ";

return 0;

}

Упражнение 13.8

Пусть дан класс Y с двумя статическими данными-членами и двумя статическими функциями-членами:

class X {

public:

X( int i ) { _val = i; }

int val() { return _val; }

private:

int _val;

};

class Y {

public:

Y( int i );

static X xval();

static int callsXval();

private:

static X _xval;

static int _callsXval;

};

Инициализируйте _xval значением 20, а _callsXval значением 0.

Упражнение 13.9

Используя классы из упражнения 13.8, реализуйте обе статические функции-члена для класса Y. callsXval() должна подсчитывать, сколько раз вызывалась xval().

Упражнение 13.10

Какие из следующих объявлений и определений статических членов ошибочны? Почему?

// example.h

class Example {

public:

static double rate = 6.5;

static const int vecSize = 20;

static vectordouble vec(vecSize);

};

// example.c

#include "example.h "

double Example::rate;

vectordouble Example::vec;