Статические функции-члены. Синтаксис, особенности применения. Фабричный метод
Статические функции-члены
Синтаксически статические и нестатические функции-члены различаются по наличию ключевого слова static в объявлении.
Аналогично переменным, задачей таких функций является инкапсуляция некоторых действий, имеющих отношение к классу, а не к его объектам.
Если реализация функции осуществляется за пределами класса, модификатор static для тела функции повторно указывать не нужно.
Поскольку статические функции-члены не имеют отношения к конкретным объектам родительского класса, в отличие от нестатических функций-членов, статическим не передается неявный указатель this.
Из отсутствия неявно передаваемого указателя this в статических функциях-членах вытекает ряд ограничений на содержащийся в их телах программный код:
1. Нельзя напрямую по имени обращаться к нестатическим переменным-членам класса, поскольку нет объекта, через который можно было бы получить к ним доступ.
2. Нельзя напрямую по имени вызывать нестатические функции-члены, поскольку нет объекта, указатель на который передавать в качестве this при вызове.
3. Нельзя совмещать модификаторы static и const, поскольку модификатор const для функций-членов влияет на тип неявно передаваемого указателя this, которого статические функции-члены не получают.
Пример кода :
student.hpp
#ifndef _STUDENT_HPP_
#define _STUDENT_HPP_
Class Student
{ // Обычные (нестатические) переменные-члены (храним в объекте)
const char * m_LastName;
Const int m_Mark;
// Статическая переменная-член (храним независимо от объектов в сегменте данных).
// Содержит текущую накопленную максимальную оценку студентов.
Static int ms_MaxMark;
public:
// Объявление конструктора
Student ( const char * _lastName, int _mark );
// Статическая функция-член: возвращает текущую накопленную максимальную оценку
Static int GetMaxMark ();
};
// Реализация статической функции-члена.
// Модификатор static в выносной реализации не указывается.
Inline int GetMaxMark ()
{
return ms_MaxMark; // Доступ к этой переменной разрешен.
// Обращаться к m_LastName или m_Mark здесь нельзя
}
#endif // _STUDENT_HPP_
student.cpp
#include “student.hpp”
// Определение статической переменной-члена, значение 0 по умолчанию
int Student::ms_MaxMark;
// Реализация конструктора
Student::Student ( const char * _lastName, int _mark )
: m_LastName( _lastName ),
M_Mark( _mark )
{ // Обновляем максимальную оценку, если новая оценка выше
if ( m_Mark > ms_MaxMark )
// Конструктор является обычной нестатической функцией-членом)
// Соответственно, может получать доступ к любой переменной класса.
ms_MaxMark = m_Mark;
}
test.cpp
#include “student.hpp”
#include <iostream>
Int main ()
{ // Создаем несколько экземпляров класса с различными оценками
Student s1( "Ivanov", 75 );
Student s2( "Petrov", 80 );
Student s3( "Sidorov", 60 );
// Выводим накопленный максимум через вызов статической функции-члена
std::cout << "Maximum mark among students: "
<< Student::GetMaxMark() // this здесь не передается
<< std::endl;
// Вызов через любой объект также возможен, tnis не передается
// ... << s1.GetMaxMark() ... <<
}
Вывод программы на консоль будет содержать следующее:
Maximum mark among students: 80
Синтаксис :
Static dataType functionName;
● functionName — имя функции
● dataType — тип данных
Фабричный метод
Например, описанный выше класс Student не должен считать корректными значения оценки за пределами интервала [1;100]. Объект, нарушающие данное инвариантное условие существовать не должен, поскольку не соблюдается важное ограничение из рассматриваемой предметной области.
Решить описанную проблему можно применением статического МЕТОДА-ФАБРИКИ (Factory Method). Такой метод будет проверять корректность переданных аргументов до момента создания объекта, а лишь убедившись в их правильности, вызовет оператор mew и конструктор
student.hpp
#ifndef _STUDENT_HPP_
#define _STUDENT_HPP_
Class Student
{ // ...
// Закрытый конструктор
Student ( const char * _lastName, int _mark );
public:
// Статический метод-фабрика
static Student* Make ( const char * _lastName, int _mark )
// ...
};
#endif // _STUDENT_HPP_
student.cpp
// ..
// Реализация конструктора
Student::Student ( const char * _lastName, int _mark )
: m_LastName( _lastName ), m_Mark( _mark )
{
}
// Реализация статического метода-фабрики
Student * Student::Make ( const char * _lastName, int _mark )
{
// Делаем проверку ограничения на оценки
if ( _mark >= 1 && _mark <= 100 )
// Все корректно, можно создавать объект