Лекция: Вызов объекта
Часто мы хотим, чтобы для какой-то задачи можно было применить и функцию, и объект заранее заданного класса. Например, в алгоритме STL std::for_each вызывается одна и та же функция для всех объектов контейнера. Мы хотим иметь возможность:
1. Вызвать для каждого элемента контейнера функцию с одним параметром, передав в качестве параметра элемент (самый простой вариант).
2. Вызвать для каждого элемента контейнера функцию с несколькими параметрами, передав в качестве одного из них элемент, а в качестве других – фиксированные значения.
3. Вызвать для каждого элемента контейнера метод его класса (возможно, с передачей дополнительных параметров). Хочется иметь возможность применить этот метод и для контейнера указателей, и для контейнера объектов.
4. Вызвать для каждого элемента контейнера метод объекта определенного класса (возможно, с передачей дополнительных параметров).
Это действительно возможно сделать. Дело в том, что шаблон std::for_each выглядит примерно так:
template <class IterType,
class FunctionType> inline
FunctionType for_each(IterType _First, IterType _Last, FunctionType _Func)
{
for ( IterType iter = _First; iter!= _Last; ++iter)
_Func( *iter );
return (_Func);
}
И в роли _Func может быть объект любого типа FunctionType – лишь бы этот объект можно было скопировать внутрь функции и вызвать, передав ему в качестве параметра *iter.
Соответственно, _Func может быть как указателем на функцию, принимающую тип элемента контейнера, так и объектом класса, имеющего метод:
void operator()( ElementType& )
Этого достаточно. Например, если хочется вызвать функцию с несколькими параметрами, мы можем написать код:
class Printer
{
public:
Printer( std::istream& stream )
:Stream(stream)
{
}
void operator()(int a )
{
Print( Stream, a );
}
private:
std::istream& Stream;
};
Printer printer( stream1 );
std::for_each( int_vector.begin(), int_vector.end(), printer );
Для каждого элемента контейнера будет вызван operator() класса Printer и, как следствие, функция Print с двумя параметрами – в качестве первого будет передан stream1, в качестве второго – элемент контейнера.