Статические функции-члены. Синтаксис, особенности применения. Фабричный метод

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

Синтаксически статические и нестатические функции-члены различаются по наличию ключевого слова 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 )

// Все корректно, можно создавать объект