Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Список экзаменационных вопросов по курсу «ООП»

§ Базовые принципы объектно-ориентированного программирования.

 

Объектно-ориентированное программирование основывается на трех основных концепциях: инкапсуляции, полиморфизме и наследовании.

 

Инкапсуляция (пакетирование) представляет собой механизм, связывающий вместе данные и код, обрабатывающий эти данные, и сохраняющий их от внешнего воздействия и ошибочного использования. Инкапсуляция позволяет создавать объект, являющийся логическим целым, включающим данные и код для работы с этими данными. Объект обеспечивает защиту против случайной или несанкционированной модификации частных (private) составляющих его членов. Закрытые данные или коды (методы) доступны только для других частей этого объекта и не доступны вне его. Открытая часть объекта предназначена для обеспечения контролируемого интерфейса его закрытой части.

 

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

 

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

 

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

 

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

 

Передача сообщений выражает основную методологию построения объектно-ориентированных программ. Программы представляются в виде набора объектов и передачи сообщений между ними.

 

При построении объектно-ориентированной программы одним из основных является вопрос иерархии классов. Пусть имеется некоторая иерархия (структура, взаимосвязь) классов. В этом случае можно:

 

- определить объект для заданного класса;

 

- построить новый класс, наследуя его из существующего класса;

 

- изменить поведение нового класса (изменить существующие и добавить новые функции).

 

Построение нового класса, наследуя его из существующего, предполагает:

 

- добавление в новый класс новых компонент-данных;

 

- добавление в новый класс новых компонент-функций;

 

- замену в новом классе наследуемых из старого класса компонент-функций;

 

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

 

Таким образом, объектно-ориентированное программирование – метод построения программ в виде множества взаимодействующих объектов, структура и поведение которых описаны соответствующими классами. Все эти классы образуют иерархию классов, выражающую отношение наследования.

 

При разработке объектно-ориентированных программ часто используются библиотеки классов. Библиотека может рассматриваться как заданная базовая иерархическая структура. Для разрабатываемой программы из библиотеки может быть выбрана некоторая подструктура и затем расширена новыми классами с использованием принципов наследования.

 

Язык программирования называется объектно-ориентированным, если:

 

- он поддерживает абстрактные типы данных (объекты с определенным интерфейсом и скрытым внутренним состоянием);

 

- объекты имеют связанные с ними типы (классы);

 

- поддерживается механизм наследования.

§ Указатель this.

Указатель – переменная, значением которой является адрес ячейки памяти. То есть указатель ссылается на блок данных из области памяти, причём на самое его начало. Указатель может ссылаться на переменную или функцию. Для этого нужно знать адрес переменной или функции. Так вот, чтобы узнать адрес конкретной переменной в С++ существует унарная операция взятия адреса &. Такая операция извлекает адрес объявленных переменных, для того, чтобы его присвоить указателю.

 

Указатели используются для передачи по ссылке данных, что намного ускоряет процесс обработки этих данных (в том случае, если объём данных большой), так как их не надо копировать, как при передаче по значению, то есть, используя имя переменной. В основном указатели используются для организации динамического распределения памяти, например при объявлении массива, не надо будет его ограничивать в размере. Ведь программист заранее не может знать, какого размера нужен массив тому или иному пользователю, в таком случае используется динамическое выделение памяти под массив. Любой указатель необходимо объявить перед использованием, как и любую переменную.

Всем не статическим методам скрытно передается указатель на сам объект, доступ к которому осуществляется через ключевое слово this/

Отметим основные правила использования this-указателей:

- каждому объявляемому объекту соответствует свой скрытый this-указа

тель;

- this-указатель может быть использован только для нестатической функ

ции;

- this указывает на начало своего объекта в памяти;

- this не надо дополнительно объявлять;

- this передается как скрытый аргумент во все нестатические (не имею

щие спецификатора static) компоненты-функции своего объекта;

- указатель this − локальная переменная и недоступна за пределами объ

екта;

- обращаться к скрытому указателю можно this или *this.

 

§ Конструкторы и деструктор.

Конструктор представляет собой метод класса, который облегчает вашим программам инициализацию элементов данных класса.

Конструктор имеет такое же имя, как и класс.

Конструктор не имеет возвращаемого значения.

Каждый раз, когда ваша программа создает переменную класса, C++ вызывает конструктор класса, если конструктор существует.

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

Деструктор имеет такое же имя, как и класс, за исключением того, что вы должны предварять его имя символом тильды (~).

Деструктор не имеет возвращаемого значения.

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

Конструктор копирования

Необходимость использования конструктора копирования вызвана тем,

что объекты наряду со статическими могут содержать и динамические данные.

В то же время, например, при передаче объекта в качестве параметра функции

в ней создается локальная (в пределах функции) копия этого объекта. При этом

указатели обоих объектов будут содержать один и тот же адрес области памя-

ти. При выводе локального объекта из поля видимости функции для его разру-

шения вызывается деструктор. В функцию деструктора входит также освобож-

дение динамической памяти, адрес которой содержит указатель. При оконча-

нии работы программы (при вызове деструкторов) производится повторная по-

пытка освободить уже освобожденную ранее память. Это приводит к ошибке.

Для устранения этого в класс необходимо добавить конструктор копирования,

который в качестве единственного параметра получает ссылку на объект клас-

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

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

В этом конструкторе выполняется выделение памяти и копирование в нее ин-

формации из объекта, получаемого по ссылке. Таким образом, указатели для

обоих объектов содержат разные адреса памяти, и при вызове деструктора вы-

полняется освобождение памяти, соответствующей каждому из объектов.

Конструктор по умолчанию

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

Деструктор

Деструктор автоматически запускается каждый раз, когда программа уничтожает объект.

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

Конструктор не имеет возвращаемого значения, но вы не указываете ему тип void. Вместо этого вы просто не указываете возвращаемое значение вообще.

Когда ваша программа создает объект, она может передать параметры конструктору во время объявления объекта.

C++ позволяет вам перегружать конструкторы и разрешает использовать значения по умолчанию для параметров.

Деструктор представляет собой специальную функцию, которую ваша программа вызывает автоматически каждый раз при уничтожении объекта. Деструктор имеет такое же имя, как и класс объекта, но его имя предваряется символом тильды (~).

§ Перегрузка бинарных операторов (+, += и других).

С базовыми типами вы можете использовать любые операции: +, -, *, ++, = и многие другие.

Перегрузка бинарного оператора

Функция operator для перегрузки (доопределения) бинарных операторов

может быть описана двумя способами:

- как компонента-функция класса с одним аргументом;

- как глобальная функция (функция, описанная вне класса) с двумя ар-

гументами.

При перегрузке бинарного оператора # выражение a#b может быть пред-

ставлено при первом способе как a.operator#(b) или как operator #(a,b) при

втором способе перегрузки.

Рассмотрим простой пример переопределения операторов *, =, > и ==

по отношению к объекту, содержащему декартовы координаты точки на плос-

кости.

§ Перегрузка унарных операторов. (++)

Перегрузка унарного оператора

При перегрузке унарной операции функция operator не имеет параметров.

Как и в предыдущем случае, модифицируемый объект передается в функцию-

operator неявным образом, используя указатель this.

Унарный оператор, как и бинарный, может быть перегружен двумя спо-

собами:

- как компонента-функция без аргументов;

- как глобальная функция с одним аргументом.

Как известно, унарный оператор может быть префиксным и постфикс-

ным. Для любого префиксного унарного оператора выражение #a может быть

представлено при первом способе как a.operator#(), а при втором как

#operator(a).

При перегрузке унарного оператора, используемого в постфиксной фор-

ме, выражение вида a# может быть представлено при первом способе как

a.operator#(int) или как operator#(a,int) при втором способе. При этом аргу-

мент типа int не существует и используется для отличия префиксной и пост-

фиксной форм при перегрузке.

Ниже приведен пример программы перегрузки оператора ++ и реализа-

ции множественного присваивания. Для перегрузки унарного оператора ++,

предшествующего оператору ++i, вызывается функция operator ++(). В случае

если оператор ++ следует за операндом i++, то вызывается функция operator++(int x), где х принимает значение 0.

 

§ Перегрузка оператора [] и ().

Функция operator может быть не только членом класса, но и friend-

функцией этого класса. Как было отмечено ранее, friend-функции, не являясь

компонентами класса, не имеют неявного указателя this. Следовательно, при

перегрузке унарных операторов в функцию operator передается один, а бинар-

ных – два аргумента. Необходимо отметить, что операторы: =, (), [] и ->

не могут быть перегружены с помощью friend-функции operator.

§ Перегрузка оператора присваивания (=).

Особенности перегрузки операции =

Доопределение оператора = позволяет решить проблему присваивания,

но не решает задачи инициализации, так как при инициализации должен вызы-

ваться соответствующий конструктор. В рассматриваемом случае это решается

использованием конструктора копирования.

Конструктор выполняет все необходимые действия при вызове функции

и копировании содержимого объекта в стек (из стека). Вызов конструктора ко-

пирования осуществляется при обращении к функции и передаче в нее в каче-

стве параметра объекта (объектов), а также возврата значения (объекта) из

функции.

§ Конструктор копирования.

Конструктор C++ при копировании одного объекта в другой работает поэлементно. То есть в переменные экземпляра класса, в который производится копирование, копируются значения из соответствующих переменных экземпляра класса, который копируется. Чаще всего нам именно такое поведение и надо - но не всегда. Например, если у нас в классе есть указатель на экземпляр другого класса, то при таком способе копируется именно указатель, т. е. в двух копиях нашего класса указатель будет указывать на одну и ту же область памяти - что нам, скорей всего, не нужно. Для того, чтобы избежать это, мы долны написать для нашего класса конструктор копирования, в котором и определить способ копирования одного экземпляра нашего класса в другой.

 

Вот пример класса с конструктором копирования:

#include <iostream.h>

 

class B{

public:

int k;

B(){

k = 0;

}

};

 

class SomeClass{

public:

B *b;

SomeClass(){

b = new B;

}

// Конструктор копирования.

SomeClass(const SomeClass & w){

this->b = new B;

this->b->k = w.b->k;

}

 

};

void main(){

SomeClass q;

SomeClass q1 = q; // Вызов конструтора копирования.

q1.b->k = 3;

cout << q.b->k;

}

 

Ситуация тут такая - в классе SomeClass есть указатель на класс B. В main мы создаем два экземпляра нашего класса SomeClass, и копируем один экземпяр в другой. Но при нашем копировании указатель на класс B не будет напрямую копироваться (т. е. адреса указателей на B у разных экземпляров класса SomeClass будут разные). И, как следствие, поменяв значение экземпляра класса B в одном экземляре класса SomeClass (в нашем случае q1) мы не поменяем значение экземпляра класса B в другом экземпляре класса SomeClass (в экземпляре q).

 

§ Static-компоненты класса.

В С++ компоненты-функции могут использоваться с модификатором static и const. Обычная компонента-функция, вызываемая

 

object. function(a,b);

 

имеет явный список параметров a и b и неявный список параметров, состоящий из компонент данных переменной object. Неявные параметры можно представить как список параметров, доступных через указатель this. Статическая (static) компонента-функция не может обращаться к любой из компонент посредством указателя this.

Ключевое слово static не должно быть включено в описание объекта статической компоненты класса. Так, в описании функции vvod_cn отсутствует ключевое слово static. В противном случае возможно противоречие между static- компонентами класса и внешними static-функциями и переменными.

Основные свойства и правила использования static- и const- функций:

 

- статические компоненты-функции не имеют указателя this, поэтому обращаться к нестатическим компонентам класса можно только с использованием. или ->;

 

- не могут быть объявлены две одинаковые функции с одинаковыми именами и типами аргументов, при этом одна статическая, а другая нет;

 

- статические компоненты-функции не могут быть виртуальными.

§ Const-компоненты функции класса.

Компонента-функция const не может изменять неявные параметры.

Функции класса, объявленные со спецификатором const, могут быть вызваны для объекта со спецификатором const, а функции без спецификатора const - не могут.

Если функция, объявленная в классе, описывается отдельно (вне класса), то спецификатор const должен присутствовать как в объявлении, так и в описании этой функции.

Основные свойства и правила использования static- и const- функций:

 

- статические компоненты-функции не имеют указателя this, поэтому обращаться к нестатическим компонентам класса можно только с использованием. или ->;

 

- не могут быть объявлены две одинаковые функции с одинаковыми именами и типами аргументов, при этом одна статическая, а другая нет;

 

- статические компоненты-функции не могут быть виртуальными.

§ Организация внешнего доступа к локальным компонентам класса (спецификатор friend)

бывают такие случаи, когда нам необходимо организовать доступ к данным объекта не используя его интерфейс (функции). Конечно, можно добавить новую public функцию к классу для получения прямого доступа к внутренним переменным. Однако, в большинстве случаев, интерфейс объекта реализует определенные операции, и новая функция может оказаться излишней. В то же время иногда возникает необходимость организации прямого доступа к внутренним (локальным) данным двух разных объектов из одной функции. При этом в С++ одна функция не может быть компонентой двух различных классов.

 

Для реализации этого в С++ введен спецификатор friend. Если некоторая функция определена как friend функция для некоторого класса, то она:

 

- не является компонентой-функцией этого класса;

 

- имеет доступ ко всем компонентам этого класса (private, public и protected).

Функции со спецификатором friend, не являясь компонентами класса, не имеют и, следовательно, не могут использовать this указатель (будет рассмотрен несколько позже). Следует также отметить ошибочность следующей заголовочной записи функции double kls:: fun(int i,int j), так как fun не является компонентой-функцией класса kls.

 

В общем случае friend-функция является глобальной независимо от секции, в которой она объявлена (public, protected, private), при условии, что она не объявлена ни в одном другом классе без спецификатора friend. Функция friend, объявленная в классе, может рассматриваться как часть интерфейса класса с внешней средой.

 

Вызов компоненты-функции класса осуществляется с использованием операции доступа к компоненте (.) или(->). Вызов же friend-функции производится по ее имени (так как friend-функции не являются его компонентами). Следовательно, как это будет показано далее, в friend-функции не передается this-указатель и доступ к компонентам класса выполняется либо явно (.), либо косвенно (->).

Отметим основные свойства и правила использования спецификатора friend:

 

- friend-функции не являются компонентами класса, но имеют доступ ко всем его компонентам независимо от их атрибута доступа;

 

- friend-функции не имеют указателя this;

 

- friend-функции не наследуются в производных классах;

 

- отношение friend не является ни симметричным (то есть если класс А есть friend классу В, то это не означает, что В также является friend классу А), ни транзитивным (то есть если A friend B и B friend C, то не следует, что A friend C);

 

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

§ Простое наследование. Открытое, защищенное и закрытое.

Открытое (public) наследование. Как уже писалось, отражает зависимость «являться». Все члены базового класса становятся членами класса-наследника (как интерфейс, так и реализация).

Закрытое (private) наследование. Об этом подробнее.

 

Пусть имеется класс B, который открыто наследует класс A. Такое наследование дает ряд преимуществ. Одним из них является то, что можно обращаться к классам-наследникам через указатель на базовый класс

§ Виртуальные функции.

В С++ виртуальные функции (virtual functions) позволяют использовать полиморфизм (polymorhpism) классов. Так как виртуальные функции могут использоваться только внутри классов, то иногда их называют виртуальными методами (virtual methods). Прежде чем воспользоваться виртуальными методами, мы рассмотрим работу обычных методов класса.

int someFunction (int arg);

int (*functionPointer)(int arg);

functionPointer = someFunction.

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

 

§ Виртуальные деструкторы.

В языке программирования C++ деструктор полиморфного базового класса должен объявляться виртуальным. Только так обеспечивается корректное разрушение объекта производного класса через указатель на соответствующий базовый класс.

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

Виртуальные деструкторы

Виртуальные деструкторы необходимы при использовании указателей на

базовый класс при выделении памяти под динамически создаваемые объекты

производных классов. Это обусловлено тем, что если объект уничтожается яв-

но, например, используя операцию delete, то вызывается деструктор только

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

учитывается тип объекта, на который указывает данный указатель.

В случае объявления деструктора базового класса виртуальным, все де-

структоры производных классов становятся также виртуальными. При этом ес-

ли будет выполняться явное уничтожение объекта производного класса для

указателя на базовый класс, то вначале вызывается деструктор производного

класса, а затем вверх по иерархии до деструктора базового класса.

§ Множественное наследование.

Множественное наследование (Multiple inheritance)— наследование от нескольких базовых классов одновременно.

Множественное наследование является способностью порожденного класса наследовать характеристики нескольких базовых классов.

Для порождения класса из нескольких базовых после имени нового класса и двоеточия вы указываете имена базовых классов, разделяя их запятыми, например class cabbit: public cat, public rabbit.

При определении конструктора производного класса вы должны вызвать конструкторы всех базовых классов, передавая им необходимые параметры.

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

 

 

§ Множественное наследование и виртуальные базовые классы

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

 

Иногда применение множественного наследования предполагает достаточно тесную связь между классами, которые рассматриваются как "братские" базовые классы. Такие классы-братья обычно должны проектироваться совместно. В большинстве случаев для этого не требуется особый стиль программирования, существенно отличающийся от того, который мы только что рассматривали. Просто на производный класс возлагается некоторая дополнительная работа. Обычно она сводится к переопределению одной или нескольких виртуальных функций (см. $$13.2 и $$8.7). В некоторых случаях классы-братья должны иметь общую информацию. Поскольку С++ - язык со строгим контролем типов, общность информации возможна только при явном указании того, что является общим в этих классах. Способом такого указания может служить виртуальный базовый класс.

 

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

§ Абстрактные базовые классы.

Абстрактный класс в объектно-ориентированном программировании — базовый класс, который не предполагает создания экземпляров. Абстрактные классы реализуют на практике один из принципов ООП - полиморфизм. Абстрактный класс может содержать (и не содержать[1]) абстрактные методы и свойства. Абстрактный метод не реализуется для класса, в котором описан, однако должен быть реализован для его неабстрактных потомков. Абстрактные классы представляют собой наиболее общие абстракции, то есть имеющие наибольший объем и наименьшее содержание.

Базовый класс иерархии типа обычно содержит ряд виртуальных функ-

ций, обеспечивающих динамическую типизацию. Часто в базовом классе эти

виртуальные функции фиктивны и имеют пустое тело. Эти функции существу-

ют как некоторая абстракция, конкретная реализация им придается в произ-

водных классах. Такие функции, тело которых не определено, называются чи-

сто виртуальными функциями. Общая форма записи чисто виртуальной

функции имеет вид

virtual прототип функции = 0;

Чисто виртуальная функция используется для того, чтобы отложить ре-

шение о реализации функции. То, что функция объявлена чисто виртуальной,

требует, чтобы эта функция была определена во всех производных классах от

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

туальную функцию, то он называется абстрактным. Для абстрактного класса

нельзя создать объекты и он используется только как базовый класс для других

классов.

Чисто виртуальную функцию, как и просто виртуальную функцию, не-

обязательно переопределять в производных классах. При этом если в произ-

водном классе она не переопределена, то этот класс тоже будет абстрактным, и

при попытке создать объект этого класса компилятор выдаст ошибку. Таким

образом, забыть переопределить чисто виртуальную функцию невозможно.

Абстрактный базовый класс навязывает определенный интерфейс всем произ-

водным от него классам. Главное назначение абстрактных классов – в опреде-

лении интерфейса для некоторой иерархии классов.

Класс можно сделать абстрактным, даже если все его функции определе-

ны. Это можно сделать, например, чтобы быть уверенным, что объект этого

класса создан не будет. Обычно для этих целей выбирается деструктор.

§ Конструктор explicit.

В С++ компилятор для конструктора с одним аргументом может автома-

тически выполнять неявные преобразования. В результате этого тип, получае-

мый конструктором, преобразуется в объект класса, для которого определен

данный конструктор.

Суть предельно ясна: один из конструкторов делегирует инициализацию другому, приводя тип своего аргумента к виду, понятному этому другому. В этом случае то, что происходит в списке инициализации, уже не повторяется.

§ Пространство имен.

При совпадении имен разных элементов в одной области действия часто

озникает конфликт имен. Наиболее часто это возникает при использовании

азличных пакетов библиотек, содержащих, например, одноименные классы.

Пространства имен используются для разделения глобального пространства

мен, что позволяет уменьшить количество конфликтов.

Пространство имён (англ. namespace) — некоторое множество, под которым подразумевается модель, абстрактное хранилище или окружение, созданное для логической группировки уникальных идентификаторов (то есть имён). Идентификатор, определенный в пространстве имён, ассоциируется с этим пространством. Один и тот же идентификатор может быть независимо определён в нескольких пространствах. Таким образом, значение, связанное с идентификатором, определённым в одном пространстве имён, может иметь (или не иметь) такое же значение, как и такой же идентификатор, определённый в другом пространстве. Языки с поддержкой пространств имён определяют правила, указывающие, к какому пространству имён принадлежит идентификатор (то есть его определение).

§ Параметризированные классы (шаблоны).

Параметризированный класс – некоторый шаблон, на основе которого

можно строить другие классы. Этот класс можно рассматривать как некоторое

описание множества классов, отличающихся только типами их данных. В С++

используется ключевое слово template для обеспечения параметрического по-

лиморфизма. Параметрический полиморфизм позволяет использовать один и

тот же код относительно различных типов (параметров тела кода). Это наибо-

лее полезно при определении контейнерных классов. Шаблоны определения

класса и шаблоны определения функции позволяют многократно использовать

код, корректно по отношению к различным типам, позволяя компилятору ав-

томатизировать процесс реализации типа.

Шаблон класса определяет правила построения каждого отдельного

класса из некоторого множества разрешенных классов.

Спецификация шаблона класса имеет вид:

template <список параметров>

class объявление класса

Список параметров класса-шаблона представляет собой идентификатор

типа, подставляемого в объявление данного класса при его генерации. Иден-

тификатору типа предшествует ключевое слово class или typename. Рассмот-

рим пример шаблона класса работы с динамическим массивом и выполнением

контроля за значениями индекса при обращении к его элементам.

§ Шаблоны функций.

В С++, так же как и для класса, для функции (глобальной, т.е. не являю-

щейся компонентой-функцией) может быть описан шаблон. Это позволит

снять достаточно жесткие ограничения, накладываемые механизмом формаль-

ных и фактических параметров при вызове функции. Рассмотрим это на при-

мере функции, вычисляющей сумму нескольких аргументов.

#include <iostream>

using namespace std;

#include <string.h>

template <class T1,class T2>

T1 sm(T1 a,T2 b) // описание шаблона

{ return (T1)(a+b); // функции c двумя параметрами

}

template <class T1,class T2,class T3>

T1 sm(T1 a,T2 b,T3 c) // описание шаблона функции

{ return (T1)(a+b+c); // функции c тремя параметрами

}

int main()

{cout<<"вызов функции sm(int,int) = "<<sm(4,6)<<endl;

cout<<"вызов функции sm(int,int,int) = "<<sm(4,6,1)<<endl;

cout<<"вызов функции sm(int,double) = "<<sm(5,.3)<<endl;

cout<<"вызов функции sm(double,int,short)= " <<

sm(.4,6,(short)1)<<endl;

// cout<<sm("я изучаю","язык С++")<<endl; error cannot add two pointers

return 0;

}

§ Шаблоны и наследование.

Шаблонные классы, как и обычные, могут использоваться повторно.

Шаблоны и наследование представляют собой механизмы повторного исполь-

зования кода и могут включать полиморфизм. Шаблоны и наследования связа-

ны между собой следующим образом:

- шаблон класса может быть порожден от обычного класса;

- шаблонный класс может быть производным от шаблонного класса;

- обычный класс может быть производным от шаблона класса.

§ Преобразование типа.

Преобразование типов — это процесс изменения типа значения. Например, можно преобразовать строку "1234" в число. Кроме того, можно преобразовать данные любого типа в тип String.

Неявные преобразования

 

В большинстве случаев преобразование типов, например, при присвоении значения переменной, происходит автоматически.Тип данных переменной определяет тип данных преобразования выражения.

Явные преобразования

 

Чтобы явным образом преобразовать выражение в определенный тип данных, используйте идентификатор этого типа, а за ним в скобках — выражение, которое нужно преобразовать.Для явного преобразования требуется написание большего объема кода, но в данном случае выше вероятность успешного результата.Кроме того, явное преобразование можно использовать в случаях, когда вероятна потеря точности.

§ Потоки ввода / вывода. Состояние потока. Пример обработки ошибки в потоке.

Классы потоков

 

К классам потоков относятся следующие:

Класс streambuf управляет буфером потока, обеспечивая базовые операции заполнения, опорожнения, сброса и прочих манипуляций с буфером.

Класс ios является базовым классом потоков ввода-вывода.

Классы istream и ostream — производные от ios и обеспечивают работу потоков соответственно ввода и вывода.

Класс iоstream является производным от двух предыдущих и предусматривает функции как для ввода, так и для вывода.

Классы ifstream, of stream и f stream предназначены для управления файловым вводом-выводом.

Классы istrstream и ostrstream управляют резидентными потоками (форматированием строк в памяти). Это устаревшая методика, оставшаяся в C++Builder в качестве пережитка.

 

Для работы с потоками вам потребуется включить в программу заголовочный файл iostream.h. Кроме того, может потребоваться подключить файлы fstream.h (файловый ввод-вывод), iomanip.h (параметризованные манипуляторы) и strstream.h (форматирование ь памяти).

 

Предопределенные потоки

 

Библиотека ввода-вывода C++ предусматривает четыре предопределенных объекта-потока, связанных со стандартными входным и выходным устройствами. Ниже дана сводка этих объектов.

Потоки istream или ostream имеют связанное с ними состояние. В классе

ios, базовом для классов istream и ostream, имеется несколько public-функций,

позволяющих проверять и устанавливать состояние потока:

inline int ios::bad() const { return state & badbit; }

inline int ios::eof() const { return state & eofbit; }

inline int ios::fail() const { return state & (badbit | failbit); }

inline int ios::good() const { return state == 0; }

§ Организация ввода / вывода, потоки. Перегрузка операторов << и >>.

§ Исключительные ситуации. Основные элементы механизма обработки исключительных ситуаций.

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

» в метод, вызвавший ошибку, при помощи ключевых слов: try, catch, trow, trowes, finally. Ключи try, catch, finally используются для формирования блока обработки исключений.

§ Генерация исключений в конструкторах.

Механизм обработки исключительных ситуаций очень

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...