Статические методы
Статические методы предназначены для обращения к статическим полям класса. Они могут обращаться непосредственно только к статическим полям и вызывать только другие статические методы класса, потому что им не передается скрытый указатель 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 не является спецификатором доступа и не наследуется.
ПРИМЕЧАНИЕ Обратите внимание на то, что класс сам определяет, какие функции и классы являются дружественными, а какие нет.