|
Программирование >> Структурное программирование
определения той части массива, которая будет выводится (см. упражнение 12.4). Шаблон функции может также быть перегружен, если мы введем другую не шаблонную функцию с тем же самым именем, но другим набором параметров функции. Например, шаблон функции printArray на рис. 12.2 мог бы быть перегружен версией не шаблонной функции, которая выводит элементы массива символьных строк в удобном табулированном виде, по столбцам (см. упражнение 12.5). Типичная ошибка программирования 12.3 Если шаблон вызывается с определяемым пользователем типом в качестве параметра и если этот шаблон использует операции (например, ==, +, <= и др.) с объектами этого типа, то такие операции должны быть перегружены! Если эти операции остались не перегруженными, то при редактировании связей будет выдано сообщение об ошибке, потому что компилятор, конечно, сгенерирует вызов соответавующих перегруженных функций-операций, не обращая внимание на то, что эти функции не определены. Компилятор выполняет некий процесс согласования, чтобы определить, какой экземпляр функции соответствует данному вызову. Сначала компилятор пытается найти и использовать функцию, которая точно соответствует по своему имени и типам параметров вызываемой функции. Если на этом этапе компилятор терпит неудачу, то он ищет шаблон функции, с помощью которого он может сгенерировать шаблонную функцию с точным соответствием типов параметров и имени функции. Если такой шаблон обнаруживается, то компилятор генерирует и использует соответствующую шаблонную функцию. Обратите внимание, что компилятор ищет шаблон, полностью соответствующий вызываемой функции по типу всех параметров; автоматическое преобразование типов не производится. И в качестве последней попытки, компилятор последовательно выполняет процесс подбора перегруженной функции, как это описано в главе 3. Типичная ошибка программирования 12.4 Компилятор подбирает вариант функции, соответавующий данному вызову. Если соответавующая функция не может быть найдена или если обнаружено несколько таких функций, то компилятор генерирует сообщение об ошибке. 12.4. Шаблоны loiaccoB Что такое стек (структура, в которую данные помещаются по одному и извлекаются в последовательности: последним вошел - первым вышел), можно понять, независимо от типа данных, помещаемых в стек. Тип данных должен быть задан только тогда, когда приходит время создать стек фактически . Здесь мы опять имеем замечательную возможность создавать универсальное программное обеспечение, которое можно использовать повторно. Нам достаточно создать некое общее описание понятия стека и на основе этого родового класса создавать классы, являющиеся специфическими версиями для конкретного типа данных . Эта возможность обеспечивается в С-Н- шаблонами классов. Замечание по технике программирования 12.3 Применение шаблонов классов увеличивает возможности повторного использования программного обеспечения, когда классы для конкретного типа данных могут создаваться на основе родовой версии класса. Шаблоны классов часто называют параметризованными типами, так как они имеют один или большее количество параметров типа, определяюш;их настройку родового шаблона класса на специфический тип данных при создании объекта класса. Для того, чтобы использовать шаблонные классы, программисту достаточно один раз описать шаблон класса. Каждый раз, когда требуется реализация класса для нового типа данных, программист, используя простую краткую запись, сообш;ает об этом компилятору, который и создает исходный код для требуемого шаблонного класса. Шаблон класса Stack, например, может служить основой для создания многочисленных классов Stack необходимых программе типов (таких, например, как Stack для данных типа floats, Stack для данных типа int , Stack для данных типа char , Stack для данных типа Етр1оуее и т. д.). Обратите внимание на описание шаблона класса Stack на рис. 12.3. Оно выглядит как традиционное описание класса, за исключением заголовка template<class Т> указывающего на то, что это описание является шаблоном класса с параметром типа Т, обозначающим тип классов Stack, которые будут создаваться на основе этого шаблона. Использовать именно идентификатор Т не обязательно, можно использовать любой другой идентификатор. Идентификатор Т определяет тип данных-элементов, хранящихся в стеке, и может использоваться в заголовке класса Stack и в функциях-элементах. TSTACK1.H Простой шаблон класса Stack #ifndef TSTACK1 H #define TSTACK1 H tinclude <iostream.h> template<class T> class Stack ! public: Stack(int = 10); -Stack 0 { delete int push(const T& int pop(T&); int isEmpty конструктор с умолчанием (размер стека равен 10) [] stackPtr; } деструктор ; помещение элемента в стек выталкивание элемента из стека int isFullО private: int size; int top; T *stackPtr; const { return top == -1; ) const { return top == size - 1; 1, если стек пустой ) 1, если стек заполнен размер стека положение вершины стека указатель на стек Рис. 12.3. Описание шаблона класса Stack (чааь 1 из 4) Конструктор с умолчанием создает объект из 10 элементов template<class Т> Stack<T>::Stack(int s) { size = s > 0 && s < 1000 ? s top = -1; stackPtr = new T[size]; 10; задается разумный размер объекта Стек, изначально, пуст выделение памяти под элементы объекта Stack Помещение элемента в стек. В случае успеха возвращается 1, в противном случае - О template<class Т> int Stack<T>::push(const Т &item) if (! isFullO ) { StackPtr[++top] = item; return 1; return 0; элемент помещается в Stack успешное завершение операция закончилась неудачей Выталкивание элемента из стека template<class Т> int Stack<T>::рор(Т SpopValue) if (! isEmpty О) { popValue = StackPtr[top-]; tendif return 1; return 0; элемент выталкивается из объекта Stack успешное завершение операции выталкивания операция закончилась неудачей Рис. 12.3. Описание шаблона класса Stack (часть 2 из 4) Теперь давайте рассмотрим программу драйвера (функцию main), в которой используется класс Stack. Программа начинается с объявления объекта floatStack размером 5 элементов. Этот объект объявляется как экземпляр класса Stack<float> (произносится как Stack типа float ). При генерации исходного кода для класса Stack типа float компилятор заменит параметр типа Т на float. Затем программа последовательно размещает значения типа float 1.1, 2.2, 3.3, 4.4 и 5.5 в созданном объекте floatStack. Цикл размещения объектов функцией push завершится после того, как программа попытается поместить в стек шестое значение (стек уже заполнен, поскольку может вмещать максимум 5 элементов). После этого программа поочередно выталкивает функцией pop все пять чисел из стека (в последовательности последним вошел - первым вышел). Программа пытается вытолкнуть и шестое значение, но так как floatStack уже пуст, то цикл выталкивания на этом завершается.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |