Статические поля и методы

Статические атрибуты

Переменные — члены класса можно объявлять как статические (static).

Используя статические переменные-члены, можнорешить несколько непростых проблем.

Если вы объявляете переменную статической, то может существовать только одна копия этой переменной — независимо от того,сколько объектов данного класса создается. Каждый объект просто использует (совместно с другими) эту одну переменную. Для обычных переменных-членов при создании каждого объекта создается их новая копия, и доступ к каждой копии возможен только через этот объект. Для обычных переменных каждый объект обладает собственными копиями переменных. А копия статической переменной — только одна, и все объекты класса используют её совместно.

Кроме этого, одна и та же статическая переменная будет использоваться всеми классами, производными от класса, в котором эта статическая переменная содержится.

При объявлении статического атрибута необходимо обеспечить для него глобальное определение вне класса. Это необходимо для того, чтобы под статический атрибут была выделена память, причём только один раз. Это делается путем нового объявления статической переменной, причем используется оператор области видимости для того, чтобы идентифицировать тот класс, к которому принадлежит переменная.

Основной смысл поддержки в C++ статических переменных-членов состоит в том, что благодаря им отпадает необходимость в использовании глобальных переменных.

Пример подсчёта созданных экземпляров

class A{
    static int counter;
    int my_number;
public:
    A()
    {
        my_number = counter;
        counter++;
    }
    int get_number() const
    {
        return my_number;
    }
};

int A::counter = 0;

int static_counter_of_instances()
{
    A a, b, c, d, e;
    A x[10];
    cout << "a number " << a.get_number() << endl;
    cout << "b number " << b.get_number() << endl;
    cout << "c number " << c.get_number() << endl;
    cout << "d number " << d.get_number() << endl;
    cout << "e number " << e.get_number() << endl;
    for (int i = 0; i < 10; i++)
        cout << "x[" << i << "] number " << x[i].get_number() << endl;
    return 0;
}

Поскольку статическая переменная — член класса существует ещё до создания объекта этого класса, доступ к ней в программе может быть реализован без всякого объекта:

int main()
{
    A::counter = 5;
    ...
}

Вопрос на засыпку

Почему при доступе к A::counter из main() в последнем случае мы получим ошибку компиляции?

Ответ

Атрибут counter описан в защищённой части класса.

Для доступа к такой переменной можно передвинуть её в зону public, но лучше сделать публичным статический метод для доступа к ней.

Статические методы

Статическими можно объявлять и методы. При этом такой метод не может обращаться к не статическим полям данного класса и не имеет в себе определённым указатель this, так как вызывается независимо от экземпляра.

Статические методы могут оказаться удобными для предварительной инициализации закрытых статических атрибутов до создания экземпляровили просто независимо от доступа к ним:

class Rabbit{
    static int max_Rabbit_size;
    int m_size;
public:
    Rabbit():m_size(max_Rabbit_size)
    {}
    static void setDefaultRabbitSize(int new_size)
    {
        //отсюда нет доступа к «экземплярному» атрибуту m_size;
        //отсюда нет доступа к this;
        max_Rabbit_size = new_size;
    }
    int getSize() const
    {
        return m_size;
    }
};
int Rabbit::max_Rabbit_size = 10;

void rabbits_field()
{
    Rabbit a;
    Rabbit::setDefaultRabbitSize(5);
    Rabbit b;
    a.setDefaultRabbitSize(20);
    Rabbit c;
    cout << "rabbit a size = " << a.getSize() << endl;
    cout << "rabbit b size = " << b.getSize() << endl;
    cout << "rabbit c size = " << c.getSize() << endl;
}