Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Операции, не изменяющие последовательность
Операции, не изменяющие последовательность данных в структуре, реализуются с помощью таких функций, как for_each() и find(), search(), count() и т.д. В листинге 19.12 показан пример использования объекта функции и алгоритм for_each, предназначенный для печати элементов вектора. Листинг 18.12. Использование алгоритма for_each() 1: #include < iostream> 2: #include < vector> 3: #include < algorithm> 4: using namespace std; 5: 6: template< class T> 7: class Print 8: { 9: public: 10: void operator()(const T& t) 11: { 12: cout < < t < < " "; 13: } 14: }; 15: 16: int main() 17: { 18: Print< int> DoPrint; 19: vector< int> vInt(5); 20: 21: for (int i = 0; i < 5; ++i) 22: vInt[i] = i * 3; 23: 24: cout < < " for_each()\n"; 25: for_each(vInt.begin(), vInt.end(), DoPrint); 26: cout < < " \n"; 27: 28: return 0; 29: }
Результат: for_each() 0 3 6 9 12
Анализ: Обратите внимание, что все стандартные алгоритмы C++ определены в файле заголовка < algorithm>, поэтому следует включить его в нашу программу. Большая часть программы не должна вызывать никаких трудностей. В строке 25 вызывается функция for_each(), чтобы опросить каждый элемент в векторе vInt. Для каждого элемента она вызывает объект функции DoPrint и передает этот элемент оператору DoPrint.operator(), что приводит к выводу на экран значения данного элемента.
Алгоритмы изменения последовательности
Под изменением последовательности понимают изменение порядка элементов в структуре данных. Изменять последовательность способны операции, связанные с заполнением или переупорядочением коллекций. Алгоритм заполнения показан в листинге 19.13. Листинг 19.13. Алгоритм изменения последовательности 1: #include < iostream> 2: #include < vector> 3: #include < algorithm> 4: using namespace std; 5: 6: template< class T> 7: class Print 8: { 9: public: 10: void operator()(const T& t) 11: { 12: cout < < t < < " "; 13: } 14: }; 15: 16: int main() 17: { 18: Print< int> DoPrint; 19: vector< int> vInt(10); 20: 21: fill(vInt.begin(), vInt.begin()+5, 1); 22: fill(vInt.begin() + 5, vInt.end(), 2); 23: 24: for_each(vInt.begin(), vInt.end(), DoPrint); 25: cout < < " \n\n"; 26: 27: return 0; 28: }
Результат: 1 1 1 1 1 2 2 2 2 2
Анализ: Единственная новая деталь в этом листинге содержится в строках 21 и 22, где используется алгоритм fill(). Алгоритм заполнения предназначен для заполнения элементов последовательности заданным значением. В строке 21 целое значение 1 присваивается первым пяти элементам в векторе vInt. А последним пяти элементам вектора vInt присваивается целое число 2 (в строке 22).
Резюме
Сегодня вы узнали, как создавать и использовать шаблоны — встроенное средство языка C++, используемое для создания параметризованных типов, т.е. типов, которые изменяют свое выполнение в зависимости от параметров, переданных при создании класса. Таким образом, шаблоны - это возможность многократного использования программного кода, причем безопасным и эффективным способом, В определении шаблона устанавливается параметризованный тип, Каждый экземпляр шаблона — это реальный объект, который можно использовать подобно любому другому объекту: в качестве параметра функции, возвращаемого значения и т.д. Классы шаблонов могут объявлять три типа функций-друзей: не относящихся к шаблону, шаблонных и специализированных по типу. В шаблоне можно объявлять статические члены. Тогда каждый экземпляр шаблона будет иметь собственный набор статических данных. Если нужно специализировать выполнение функции шаблона в зависимости от типа, то ее можно замещать для разных типов.
Вопросы и ответы
Чем использование шаблонов лучше использования макросов? Шаблоны обеспечивают более безопасное использование разных типов и встроены в язык. Какова разница между параметризованным типом функции шаблона и параметрами обычной функции? Обычная функция (не шаблонная) принимает параметры, с которыми может выполнять заданные действия. Функция шаблона позволяет с помощью параметра шаблона устанавливать тип передаваемого параметра функции. Так, в функцию можно передать массив объектов, тип которых будет уникален для разных экземпляров шаблона. Когда следует использовать шаблоны, а когда наследование? Используйте шаблоны в том случае, когда все или почти все выполнение класса остается неизменным, а изменяется только тип данных, используемых в классе. Когда использовать дружественные шаблонные классы и функции? Когда каждый экземпляр, независимо от типа, должен быть другом по отношению к этому классу или функции. Когда использовать дружественные шаблонные классы или функции, специализированные по типу? Когда между двумя классами нужно установить отношения по типу один-к-одному. Например, массив array< lnt> должен соответствовать итератору iterator< int>, но не iterator< Animal>. Каковы два типа стандартных контейнеров? Последовательные и ассоциативные контейнеры. Последовательные контейнеры обеспечивают оптимизированный последовательный и произвольный доступ к своим элементам. Ассоциативные контейнеры обеспечивают оптимизированный доступ к элементам на основе ключевых значений. Какими атрибутами должен обладать класс, чтобы его можно было использовать со стандартными контейнерами? В классе должны быть явно определены стандартный конструктор, конструктор- копировщик и перегруженный оператор присваивания.
|