• string
и vector
, демонстрирующие сильную зависимость между абстракциями данных и параметризацией, используемой в обобщенном программировании. Слово “абстракция” используется в названии этой парадигмы потому, что взаимодействие с типом осуществляется посредством интерфейса, а не прямого доступа к его реализации.
•
• high()
, описанная в главе 20. Алгоритмы find()
и sort()
из библиотеки являются классическими алгоритмами поиска и сортировки, выраженными в очень общей форме с помощью обобщенного программирования. См. также примеры в главах 20-21.
Рассмотрим пример: классический класс Shape
, возникший в языке Simula (раздел 22.2.4), который обычно считается воплощением объектно-ориентированного программирования. Первое решение может выглядеть так:
void draw_all(vector
{
for(int i = 0; i
}
Этот фрагмент кода действительно выглядит “довольно объектно-ориентированным”. Он основан на иерархии классов и вызове виртуальной функции, при котором правильная функция draw()
для каждого конкретного объекта класса Shape
находится автоматически; иначе говоря, для объекта класса Circle
он вызовет функцию Circle::draw()
, а для объекта класса Open_polyline
— функцию Open_polyline::draw()
. Однако класс vector
по существу является конструктивным элементом обобщенного программирования: он использует параметр (тип элемента), который выясняется на этапе компиляции. Следует подчеркнуть, что для итерации по всем элементам используется алгоритм из стандартной библиотеки.
void draw_all(vector
{
for_each(v.begin(),v.end(),mem_fun(&Shape::draw));
}
Третьим аргументом функции for_each()
является функция, которая должна вызываться для каждого элемента последовательности, заданной двумя первыми аргументами (раздел Б.5.1). Предполагается, что третья функция представляет собой обычную функцию (или функцию-объект), которая вызывается с помощью синтаксической конструкции f(x)
, а не функцию-член, вызываемую с помощью синтаксической конструкции p–>f()
. Следовательно, для того чтобы указать, что на самом деле мы хотим вызвать функцию-член (виртуальную функцию Shape::draw()
), необходимо использовать стандартную библиотечную функцию mem_fun()
(раздел Б.6.2). Дело в том, что функции for_each()
и mem_fun()
, будучи шаблонными, на самом деле не очень хорошо соответствуют объектно-ориентированной парадигме; они полностью относятся к обобщенному программированию. Еще интереснее то, что функция mem_fun()
является автономной (шаблонной) функцией, возвращающей объект класса. Другими словами, ее следует отнести к простой абстракции данных (нет наследования) или даже к процедурному программированию (нет сокрытия данных). Итак, мы можем констатировать, что всего лишь одна строка кода использует все четыре фундаментальных стиля программирования, поддерживаемых языком C++.