Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП.docx
Скачиваний:
7
Добавлен:
01.07.2025
Размер:
68.18 Кб
Скачать

6.2 Шаблоны классов

По аналогии с параметризованной функцией можно построить параметризованное описание класса, позволяющее создавать экземпляры классов для конкретных значений параметров. Параметризованный класс описывается следующим образом:

template <class T >

class описание класса

Как и для функций, в описателе template может быть задано несколько параметров. В самом описание класса имена параметров используются как имена типов данных, типов параметров функций и типов значений, возвращаемых функциями.

В качестве примера приведем описание класса stack, предназначенного для построения стеков фиксированного максимального размера с элементами произволного типа.

enum BOOLEAN ( FALSE, TRUE );

template <class Type >

class stack

{ private:

enum ( EMPTY = -1 );

Type* s; /* Указатель на массив стека */

int max_len; /* Максимальная длина стека */

int top; /* Индекс элемента в вершине стека */

public:

stack ( ) : max_len ( 100 ) /* конструктор без параметров */

{ s = new Type [ 100 ]; top = EMPTY; }

stack ( int size ) : max_len( size ) /* Второй конструктор */

{ s = new Type [ size ]; top = EMPTY; }

~stack ( ) { delete [ ] s; } /* Деструктор */

void reset ( ) { top = EMPTY; } /* Очистить стек */

void push ( Type c ) { s [ ++top ] = c; }

Type pop ( ) { return (s [top—] }

Type top_of ( ) { return ( s [top ] }

BOOLEAN empty ( ) { return BOOLEAN ( top == EMPTY ) }

BOOLEAN full ( ) { return BOOLEAN ( top == max_len ) }

};

Следует отметить, что в этом примере с целью сокращения исходного текста не предусмотрен контроль выхода за пределы стека в методах push и pop.

Чтобы создать экземпляр параметризованного объектного типа, нужно уточнить имя типа значением параметра в угловых скобках:

stack < int > stack_of_int (50); /* Стек на 50 элементов типа int */

stack < myClass > stmc (20); /* Стек на 20 элементов типа myClass */

В приведенном примере все компоненты-функции определены в описании класса. Когда полное определение функции-члена класса задается вне описания класса, оно должно уточняться описателем template. Например, если бы метод top_of был определен вне описания класса, определение имело бы вид:

template < class Type >

Type top_of ( ) { return s [ top ];}

Отметим некоторые специфические черты описаний параметризованных классов.

Если в параметризованном классе определены friend-функции, то когда такая функция не зависит от параметра, будет использоваться единственная friend-функция для всех значений параметра, а когда friend-функция зависит от параметра, будет использоваться своя friend-функция для каждого значения параметра.

Если в параметризованном классе имеются статические (static) компоненты, то для каждого значения параметра будет использоваться свой экземпляр статической компоненты.

Контрольные вопросы. (какие есть)

7

Новый класс строится на базе уже существующего с помощью конструкции следующего вида.

class Parent {....};

class Child : [модификатор наследования] Parent {....};

Модификатор наследования определяет, какие права доступа к переменным и методам класса-родителя будут переданы классу-потомку. При реализации наследования область видимости принадлежащих классу данных и методов можно определять выбором ключевого слова private (собственный), public (общедоступный) или protected (защищенный), которые могут произвольно чередоваться внутри описания класса.

Модификатор доступа Модификатор наследования

public protected private

Public Public Protected Private

Protected Protected Protected Private

private Нет доступа Нет доступа Нет доступа

13

С помощью параметра-ссылки или параметра-указателя.

17

Возможно. При передаче объекта в функцию появляется новый объект. Когда работа функции, которой был передан объект, завершается, то удаляется копия аргумента. Но, что объект внутри функции - это побитовая копия передаваемого объекта, а это значит, что если объект содержит в себе, например, некоторый указатель на динамически выделенную область памяти, то при копировании создается объект, указывающий на ту же область памяти. И как только вызывается деструктор копии, где, как правило, принято высвобождать память, то высвобождается область памяти, на которую указывал объект-«оригинал», что приводит к разрушению исходного объекта.

20.

Ссылка является скрытым указателем и всегда работает в качестве другого (дополнительного) имени переменной. При применении параметра-ссылки компилятор передает адрес переменной, используемой в качестве аргумента. Внутри функции компилятор использует переменную, на которую ссылается параметр-ссылка. В отличие от передачи параметра по значению, использование ссылки предполагает, что функция, в которую передан данный параметр, будет манипулировать не копией передаваемого объекта, а непосредственно самим передаваемым объектом.

Параметры-ссылки имеют некоторые преимущества по сравнению с аналогичными альтернативными параметрами-указателями. Во-первых, нет необходимости получать и передавать в функцию адрес аргумента, адрес передается автоматически. Во-вторых, ссылки предлагают более понятный и элегантный интерфейс, чем неуклюжий механизм указателей.

Ссылки могут также использоваться в качестве возвращаемого значения функции. Обычно такой механизм применяется в сочетании со ссылкой-параметром или указателем this.

Но:

• Вы не можете получить адрес ссылки, используя оператор адреса C++.

• Вы не можете присвоить ссылке указатель.

• Вы не можете сравнить значения ссылок, используя операторы сравнения C++.

• Вы не можете выполнить арифметические операции над ссылкой, например добавить смещение.

•Вы не можете изменить ссылку.

22.

Любой конструктор копирования имеет следующую форму.

имя_класса (const имя_класса & obj)

{

... // тело конструктора

}

Конструктор копирования вызывается всякий раз, когда создается копия объекта. Во-первых, при передаче объекта в качестве параметра функции. Во-вторых, при создании временного объекта тогда, когда функция в качестве возвращаемого значения использует объект. В-третьих, - это инициализация одного объекта другим.

30.

В случае раннего связывания адреса всех функций и процедур известны в тот момент, когда происходит компоновка программы. Логика компилятора очень проста. Сначала он ищет метод с нужным именем, определенный внутри данного класса. Если метод с таким именем внутри класса не определен, то компилятор обращается к базовому классу и ищет этот метод там. Если найдет, то подставит в точки вызова адрес метода из родительского класса. Если не найдет, то поднимется по иерархическому дереву еще выше.

В противоположность этому в случае позднего связывания адрес процедуры не связывается с обращением к ней до того момента, пока обращение не произойдет фактически, то есть во время выполнения программы.

Различие между вызовом статического метода и вызовом виртуального метода - это различие между решением немедленным и отложенным, задержанным решением.

31.

совместимость имеет три формы:

• между экземплярами объектов;

• между указателями объектов;

• между формальными и фактическими параметрами.

Однако во всех трех формах необходимо запомнить, что совместимость типов распространяется от потомка к предку. Родительскому объекту можно присваивать объект любого порожденного им класса. Обратные присваивания неверны.

Объекту абстрактному классу можно присвоить любой объект-потомок