Материал: статметоды, конструкторы, деструкторы

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

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

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

class A{

static int count; // Поле count -- скрытое

     public:

static void inc_count(){ count++; }

...

};

...

A::int count; // Определение в глобальной области

void f(){

     A a;

     // a.count++ -- нельзя, поле count скрытое

     // Изменение поля с помощью статического метода:

     a.inc_count(); // или A::inc_count();

}

    Статические методы не могут быть константными (const) и виртуальными (virtual).

Дружественные функции и классы

    Иногда желательно иметь непосредственный доступ извне к скрытым полям класса, то есть расширить интерфейс класса. Для этого служат дружественные функции и дружественные классы.

Дружественная функция

    Дружественные функции применяются для доступа к скрытым полям класса и представляют собой альтернативу методам. Метод, как правило, описывает свойство объекта, а в виде дружественных функций оформляются действия, не являющиеся свойствами класса, но концептуально входящие в его интерфейс и нуждающиеся в доступе к его скрытым полям, например, переопределенные операции вывода объектов.

    Ниже перечислены правила описания и особенности дружественных функций.

  • Дружественная функция объявляется внутри класса, к элементам которого ей нужен доступ, с ключевым словом friend. В качестве параметра ей должен передаваться объект или ссылка на объект класса, поскольку указатель this ей не передается.

  • Дружественная функция может быть обычной функцией или методом другого ранее определенного класса. На нее не распространяется действие спецификаторов доступа, место размещения ее объявления в классе безразлично.

  • Одна функция может быть дружественной сразу нескольким классами.

  •     В качестве примера ниже приведено описание двух функций, дружественных классу monstr. Функция kill является методом класса hero, а функция steal_ammo не принадлежит ни одному классу. Обеим функциям в качестве параметра передается ссылка на объект класса monstr.

class monstr; // Предварительное объявление класса

class hero{

     public:

void kill(monstr &);

     ...

};

class monstr{

     ...

     friend int steal_ammo(monstr &);

     friend void hero::kill(monstr &);

     // Класс hero должен быть определен ранее

};

int steal_ammo(monstr &M){return --M.ammo;}

void hero::kill(monstr &M){M.health = 0; M.ammo = 0;}

    Использования дружественных функций нужно по возможности избегать, поскольку они нарушают принцип инкапсуляции и, таким образом, затрудняют отладку и модификацию программы.

Дружественный класс

    Если все методы какого-либо класса должны иметь доступ к скрытым полям другого, весь класс объявляется дружественным с помощью ключевого слова friend. В приведенном ниже примере класс mistress объявляется дружественным классу hero:

class hero{

     ...

     friend class mistress;

}

class mistress{

     ...

     void f1();

     void f2();

}

    Функции f1 и f2 являются дружественными по отношению к классу hero (хотя и описаны без ключевого слова friend) и имеют доступ ко всем его полям.

    Объявление friend не является спецификатором доступа и не наследуется.

ПРИМЕЧАНИЕ Обратите внимание на то, что класс сам определяет, какие функции и классы являются дружественными, а какие нет.

Деструкторы

    Деструктор -- это особый вид метода, применяющийся для освобождения памяти, занимаемой объектом. Деструктор вызывается автоматически, когда объект выходит из области видимости:

  • для локальных объектов -- при выходе из блока, в котором они объявлены;

  • для глобальных -- как часть процедуры выхода из main;

  • для объектов, заданных через указатели, деструктор вызывается неявно при использовании операции delete.

ВНИМАНИЕ Автоматический вызов деструктора объекта при выходе из области действия указателя на него не производится.

    Имя деструктора начинается с тильды (~), непосредственно за которой следует имя класса. Деструктор:

  • не имеет аргументов и возвращаемого значения;

  • не может быть объявлен как const или static;

  • не наследуется;

  • может быть виртуальным (см. раздел "Виртуальные методы").

    Если деструктор явным образом не определен, компилятор автоматически создает пустой деструктор.

    Описывать в классе деструктор явным образом требуется в случае, когда объект содержит указатели на память, выделяемую динамически -- иначе при уничтожении объекта память, на которую ссылались его поля-указатели, не будет помечена как свободная. Указатель на деструктор определить нельзя.

    Деструктор для рассматриваемого примера должен выглядеть так:

monstr::~monstr() {delete [] name;}

    Деструктор можно вызвать явным образом путем указания полностью уточненного имени, например:

monstr *m; ...

m -> ~monstr();

    Это может понадобиться для объектов, которым с помощью перегруженной операции new выделялся конкретный адрес памяти. Без необходимости явно вызывать деструктор объекта не рекомендуется.