Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Класс - (обобщенный) структурный тип.






Класс – это набор компонентов возможно разного типа. Способ группировки аналогичен записям/структурам, но

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

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

Методы - компоненты-операции класса, они задают процедуры и функции для работы с такими значениями.

 

Object Pascal 2 C (C++)
Определение типа класс: ИмяТипаКласс = class [СпецификаторНаследования] СекцияКомпонентов... end ¨ СпецификаторНаследования может отсутствовать, это понятие рассмотрим позже. ¨ СекцияКомпонентов начинается с ключевого слова, которое специфицирует область видимости компонентов секции: § private – секция инкапсулированных (закрытых) компонентов; § public – секция интерфейсных (открытых) компонентов; § protected – секция защищенных компонентов. У первой секции эту спецификацию можно опустить, тогда она считается public–секцией. Далее в секции следуют: § объявления полей - точно также как в записях, § объявления методов – заголовки (прототипы) процедур или функций. В секции могут отсутствовать поля или методы, но объявление метода секции не может предшествовать ни одному объявлению поля этой секции. Фактически каждое объявление должно заканчиваться точкой с запятой (разделяющей их), но перед end описателя класса точку с запятой можно опустить, если последним в классе объявлено поле. Определение типа класс: class ИмяТипаКласс [СпецификаторНаследования] { СекцияКомпонентов... } ¨ СпецификаторНаследования может отсутствовать, это понятие рассмотрим позже. ¨ СекцияКомпонентов начинается с ключевого слова (с двоеточием), которое специфицирует область видимости компонентов секции: § private: – секция инкапсулированных (закрытых) компонентов; § public: – секция интерфейсных (открытых) компонентов; § protected: – секция защищенных компонентов. У первой секции эту спецификацию можно опустить, тогда она считается private–секцией. Далее в секции следуют: § объявления полей – точно также как в структурах, § объявления методов – заголовки (прототипы) функций. В секции могут отсутствовать поля или методы.  

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

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

В модуле реализация методов класса отделена от определения класса, поэтому в заголовке описания метода (процедуры-функции) имя метода уточняется именем класса:

§ В Object Pascal 2: ИмяКласса.

§ В C++: ИмяКласса::

Если процедура или функция описана в модуле без уточнения именем класса, то она трактуется как обычная процедура-функция модуля, никак не связанная ни с каким классом (не трактуется как метод какого-либо класса).

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

Описание переменных типа класс (как всегда) :

ИмяПеременной,...: T class T class ИмяПеременной,...;

Переменные типа класс расширяют семантику понятия «переменная»:

¨ Компоненты такой переменной хранят не только данные, но и информацию об операциях с этими данными, кроме того компоненты такой переменной могут быть инкапсулированы (не видимы для «посторонних»).

¨ Переменные типа класс – это специальный вид динамических переменных:

  • переменные типа класс, в отличие от динамических переменных ранее рассмотренного вида, должны быть описаны, но не создаются неявно (как это происходит согласно семантике локальных переменных);

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


Конструкторы и деструкторы – это методы класса, нагруженные дополнительной специальной семантикой.

Объявление конструктора и деструктора класса: Конструкторы и деструкторы класса объявляются также как методы-процедуры, но с ключевым словом constructor и destructor соответственно, вместо procedure. Объявление конструктора и деструктора класса: Конструкторы и деструкторы класса объявляются также как методы-процедуры, но без void, как признак невозвращения значения, и имя конструктора дожно совпадать с ИмяТипаКласс, а имя деструктора дожно совпадать с ~ ИмяТипаКласс.
Вызов конструктора (базовый вариант): V class: = ИмяТипаКласс. ИмяКонструктора [ ( ФактическийПараметр,...) ] Такой вызов конструктора: § создает хранилище данных для хранения значения типа ИмяТипаКласс, V class будет обозначением для этого хранилища; § выполняется тело конструктора (настроеное по параметрам), обычно это инициализация полей переменной типа класс. Вызов конструктора (базовый вариант): В базовом варианте конструктор вызывается в объявлении переменной типа класс согласно семантике такого объявления, т.е. в некотором определенном смысле неявно (*). Причем, так может быть вызыван только конструктор по умолчанию: § это конструктор, который можно вызвать с пустым списком фактических параметров; § если в классе нет объявлений конструкторов, то такой конструктор строится автоматически (с пустым телом); § если в классе есть объявление хотя бы одного конструктора, но среди них нет конструктора по умолчанию, то имеем ситуацию фатальной ошибки периода выполнения.
  T class ИмяПеременной; Такой вызов конструктора по умолчанию: § создает хранилище данных для хранения значения типа T class, ИмяПеременной будет обозначением для этого хранилища; § выполняется тело конструктора, обычно это инициализация полей переменной типа класс.
Компонентная переменная: § Выборка поля: V class. ИмяПоля Тип этой переменной - тот, который в определении класса объявлен для поля ИмяПоля.
§ Вызов метода: V class. ИмяМетода [ ( ФактическийПараметр,...) ] § Вызов метода-функции: V class. ИмяМетода ([ ФактическийПараметр,... ]) § Вызов метода-процедуры (функции, не возвращающей значение): V class. ИмяМетода ([ ФактическийПараметр,... ]);
Вызов метода-процедуры вляется оператором S, а вызов метода-функции – выражением E.

Ø Вариант 4. Динамическая реализация стеков и использование классов и модулей.

Чисто технически новая реализация очень близка к ранее рассмотренной «Вариант 2», поэтому на следующей странице они обе представлены для визуального сравнения.

В новой реализации решены вышерассмотренные проблемы:

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

§ теперь можно описать (и создать) переменные типа стек:

VAR OStack1, OStack2: CStack; BEGIN...

OStack1: =CStack.MakeNull;... OStack2: =CStack.MakeNull;...

§ операции теперь являются составной частью каждой переменной типа CStack, соответственно они и применяются свои для каждой переменной:

y1: =OStack1.Top; OStack1.Pop;...

y2: =OStack2.Top; OStack2.Pop;...

¨ «Уши» внутреннего представления стека «торчат» в секции INTERFACE, но «вытащить за эти уши» компоненты внутреннего представления стека и испортить их, уже возможности нет - само хранилище стека Stack защищено и недоступно извне.


UNIT UStack;

INTERFACE USES UVal;

FUNCTION Empty: BOOLEAN {Проверить на пустоту};

PROCEDURE Push(xPrm: UVal.TVal){Добавить, положить в стек};

PROCEDURE Pop {Удалить, вытолкнуть из стека};

FUNCTION Top: UVal.TVal {Посмотреть вершину};

PROCEDURE WriteAll {Вывести все элементы стека};

VAR ErrStack: INTEGER {Код ошибки};

IMPLEMENTATION

TYPE PElement=^TElement;

TElement= RECORD VElem: UVal.TVal; Next: PElement END;

TStack= PElement;

VAR Stack: TStack;

 

 

FUNCTION Empty: BOOLEAN; BEGIN Empty: =(Stack=NIL) END;

PROCEDURE Push(xPrm: UVal.TVal); VAR p: PElement;

BEGIN NEW(p); p^.VElem: =xPrm; p^.Next: =Stack; Stack: =p END;

PROCEDURE Pop; VAR xStack: PElement;

BEGIN IF Stack=NIL THEN {недопустима - стек пустой} ErrStack: =-2

ELSE BEGIN xStack: =Stack^.Next;

Dispose(Stack); Stack: =xStack END END;

FUNCTION Top;

BEGIN IF Stack=NIL THEN {недопустима - стек пустой} ErrStack: =-2

ELSE Top: =Stack^.VElem END;

PROCEDURE WriteAll; VAR p: PElement; BEGIN p: =Stack;

WHILE p< > NIL DO BEGIN WriteElement(Stack^.VElem); p: =p^.Next

END

END;

INITIALIZATION Stack: =NIL; ErrStack: =0

END.

program Project1;

uses UVal in 'UVal.pas', UStack in 'UStack.pas';

VAR Vh, Vih: FILE OF CHAR; x, y: CHAR;

begin RESET(Vh); REWRITE(Vih);

 

WHILE NOT EOF(Vh) DO BEGIN READ(Vh, x);

CASE x OF

'(':;

'+', '-', '*', '/': UStack.Push(x);

')': BEGIN y: =UStack.Top; WRITE(Vih, y); UStack.Pop END;

ELSE {'a'..'z'} WRITE(Vih, x);

END END; CloseFile(Vh); CloseFile(Vih) end.


UNIT UStack;

INTERFACE USES UVal;

TYPE PElement=^TElement;

TElement= RECORD VElem: UVal.TVal; Next: PElement END;

TStack= PElement;

CStack= CLASS PRIVATE Stack: TStack; PUBLIC

ErrStack: INTEGER {Код ошибки};

FUNCTION Empty: BOOLEAN {Проверить на пустоту};

PROCEDURE Push(xPrm: UVal.TVal){Добавить, положить в стек};

PROCEDURE Pop {Удалить, вытолкнуть из стека};

FUNCTION Top: UVal.TVal {Посмотреть вершину};

PROCEDURE WriteAll {Вывести все элементы стека};

CONSTRUCTOR MakeNull {Создать пустой стек};

END;

IMPLEMENTATION

FUNCTION CStack.Empty: BOOLEAN; BEGIN Empty: =(Stack=NIL) END;

PROCEDURE CStack.Push(xPrm: UVal.TVal); VAR p: PElement;

BEGIN NEW(p); p^.VElem: =xPrm; p^.Next: =Stack; Stack: =p END;

PROCEDURE CStack.Pop; VAR xStack: PElement;

BEGIN IF Stack=NIL THEN {недопустима - стек пустой} ErrStack: =-2

ELSE BEGIN xStack: =Stack^.Next;

Dispose(Stack); Stack: =xStack END END;

FUNCTION CStack.Top: UVal.TVal;

BEGIN IF Stack=NIL THEN {недопустима - стек пустой} ErrStack: =-2

ELSE Top: =Stack^.VElem END;

PROCEDURE CStack.WriteAll; VAR p: PElement; BEGIN p: =Stack;

WHILE p< > NIL DO BEGIN WriteElement(Stack^.VElem); p: =p^.Next

END

END;

CONSTRUCTOR CStack.MakeNull; BEGIN Stack: =NIL; ErrStack: =0 END;

END.

program Project1;

uses UVal in 'UVal.pas', UStack in 'UStack.pas';

VAR Vh, Vih: FILE OF CHAR; x, y: CHAR; OStack: CStack;

begin RESET(Vh); REWRITE(Vih);

OStack: =UStack.CStack.MakeNull;

WHILE NOT EOF(Vh) DO BEGIN READ(Vh, x);

CASE x OF

'(':;

'+', '-', '*', '/': OStack.Push(x);

')': BEGIN y: =OStack.Top; WRITE(Vih, y); OStack.Pop END;

ELSE {'a'..'z'} WRITE(Vih, x);

END END; CloseFile(Vh); CloseFile(Vih) end.

PROGRAM\Prg3d\Project1.dpr

Файл UStack.h:

void MakeNull(); //Создать пустой стек

bool Empty(); //Проверить на пустоту

void Push(TVal xPrm); //Добавить, положить в стек

void Pop(); //Удалить, вытолкнуть из стека

TVal Top(); //Посмотреть вершину

void WriteAll(); //Вывести все элементы стека

extern int ErrStack; //Код ошибки

Файл UStack.cpp:

#include " UVal.h"

int ErrStack; //Код ошибки

struct TElement {TVal VElem; TElement* Next; };

static TElement* Stack;

 

bool Empty() //Проверить на пустоту

{return (Stack==NULL); }

void Push(TVal xPrm) //Добавить, положить в стек

{TElement* p; p=new(TElement); p-> VElem=xPrm; p-> Next=Stack;

Stack=p; }

void Pop() //Удалить, вытолкнуть из стека

{TElement* xStack;

if(Stack==NULL) ErrStack=-2; //недопустима - стек пустой

else{ xStack=Stack-> Next; delete(Stack); Stack=xStack; }}

TVal Top() //Посмотреть вершину

{if(Stack==NULL) ErrStack=-2; //недопустима - стек пустой

else return Stack-> VElem; }

void WriteAll() //Вывести все элементы стека

{TElement* p; p=Stack;

while(p! =NULL){ WriteElement(Stack-> VElem); p=p-> Next; }}

void MakeNull() //Создать пустой стек

{Stack=NULL; ErrStack=0; }

Файл prg3b.cpp:

#include " UVal.h"

#include " UStack.h"

main(){ifstream Vh/*входной текст*/; ofstream Vih/*выходной текст*/;

char x/*текущий символ*/, y;

Vh.open(" VhPrg3.TXT"); Vih.open(" VihPrg3.TXT"); MakeNull();

while(Vh.peek()! =EOF){ Vh.get(x); switch (x) {

case '(': break;

case '+': case '-': case '*': case '/': Push(x); break;

case ')': Vih< < Top(); Pop(); break;

default: /*'a'..'z'*/ Vih< < x;

}} Vh.close(); Vih.close(); }


Файл UStack.h:

struct TElement {TVal VElem; TElement* Next; };

class CStack{ private: TElement* Stack; public:

int ErrStack; //Код ошибки

bool Empty(); //Проверить на пустоту

void Push(TVal xPrm); //Добавить, положить в стек

void Pop(); //Удалить, вытолкнуть из стека

TVal Top(); //Посмотреть вершину

void WriteAll(); //Вывести все элементы стека

CStack(); //MakeNull - Создать пустой стек

};

Файл UStack.cpp:

#include " UVal.h"

#include " UStack.h"

bool CStack:: Empty() //Проверить на пустоту

{return (Stack==NULL); }

void CStack:: Push(TVal xPrm) //Добавить, положить в стек

{TElement* p; p=new(TElement); p-> VElem=xPrm; p-> Next=Stack;

Stack=p; }

void CStack:: Pop() //Удалить, вытолкнуть из стека

{TElement* xStack;

if(Stack==NULL) ErrStack=-2; //недопустима - стек пустой

else{ xStack=Stack-> Next; delete(Stack); Stack=xStack; }}

TVal CStack:: Top() //Посмотреть вершину

{if(Stack==NULL) ErrStack=-2; //недопустима - стек пустой

else return Stack-> VElem; }

void CStack:: WriteAll() //Вывести все элементы стека

{TElement* p; p=Stack;

while(p! =NULL){ WriteElement(Stack-> VElem); p=p-> Next; }}

CStack:: CStack() //MakeNull - Создать пустой стек

{Stack=NULL; ErrStack=0; }

Файл prg3d.cpp:

#include " UVal.h"

#include " UStack.h"

main(){ifstream Vh/*входной текст*/; ofstream Vih/*выходной текст*/;

char x/*текущий символ*/, y; CStack OStack;

Vh.open(" VhPrg3.TXT"); Vih.open(" VihPrg3.TXT"); //OStack=CStack();

while(Vh.peek()! =EOF){ Vh.get(x); switch (x) {

case '(': break;

case '+': case '-': case '*': case '/': OStack.Push(x); break;

case ')': Vih< < OStack.Top(); OStack.Pop(); break;

default: /*'a'..'z'*/ Vih< < x;

}} Vh.close(); Vih.close(); }

PROGRAM\C(C++)\prg3d\prg3d.dsw


Реализация очередей.

Ø Вариант 1. Статическая реализация очередей.

Также как в случае статической реализации стека, используем вектор для представления очереди. Также как и в задаче о порождении обобщенно-периодичной последовательности мы столкнемся с «неприятностью» - при каждом удалении первого компонента очереди придется передвигать все остальные, поэтому «замкнем вектор в кольцо»(*). Поскольку операции добавления-удаления (с разных концов) могут выполняться в (почти) любом порядке, придется хранить позицию как первого (Front), так и последнего (Rear) компонента очереди.

CONST CMaxL=1000;

TYPE... RECORD Elem: ARRAY[1..CMaxL] OF UVal.TVal;

Front, Rear: 0..CMaxL END;

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

очередь максимальной длины (Front..Rear по часовой стрелке) или пустую очередь? Устранить эту двусмысленность можно, не допуская того чтобы «Rear мог догнать Front», т.е. ограничив максимальную длину очереди величиной строго меньшей, чем длина представляющего вектора. PROGRAM\Prg4d0\Project1.dpr

Ø Вариант 2. Динамическая реализация очередей.

PROGRAM\PRG4D2\Project1.dpr PROGRAM\C(c++)\prg4d2\prg4d.dsw

PROGRAM\Prg4d\Project1.dpr PROGRAM\C(c++)\PRG4D\prg4d.dsw

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


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.029 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал