Реферат: Объективное программирование

ВВЕДЕНИЕ  В ОБЪЕКТНОЕ ПРОГРАММИРОВАНИЕ

Лекция 1.Объектное программирование как технология программирования

-------------------------------------------------------------

     Традиционная технология программирования70-х годов — структурное программирование:

     — модульное программирование;

     — нисходящее программирование;

     — структурное проектирование процедур иданных (программирование без goto).

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

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

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

отображаемымипрограммой,  и програмнными объектами,являющимися,по  существу,  структурированными  переменными (в дальнейшем под термином«объект» будем понимать программный объект).

Традиционныйподход:  ----------    переменная      тип данных

Объектно-ориентиро-  физический   программный     класс

ванныйподход:        объект        объект          объектов

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

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

     Объектно-ориентированные программы можноразрабатывать  и  спомощью традиционных языков программирования. Рассмотрим пример определенияобъектов типа «дата» на классическом Си.

//------структура dat — аналог класса объектов «дата» --------typedef structdat

        {

        unsigned day;

        unsigned month;

        unsigned year;

        }

        DAT;

//-----набор функций для класса объектов «дата» --------------static  int    mm[] = {31,28,31,30,31,30,31,31,30,31,30,31};

//-----Проверка  на корректность-----------------------------int    TestData(p)

DAT     *p;

{

if(p->month ==2 && p->day==29 && p->year %4 ==0)return(1);

if(p->month ==0 || p->month >12 ||

    p->day ==0 || p->day>mm[p->month])

        return(0);

return(1);

}

//------Следующая дата ----------------------------------------void    NextData(p)

DAT     *p;

{

p->day++;

if(p->day <= mm[p->month]) return;

if(p->month ==2 && p->day==29 && p->year %4 ==0) return;

p->day=1;

p->month++;

if(p->month !=13) return;

p->month=1;

p->year++;

}

//-------Следующая дата через n дней --------------------------void    PlusData(p,n)

DAT     *p;

int     n;

{

while(n-- !=0) NextData(p);

}

//-------Основная программа ---------------------------------

voidmain()

{

DAT a;

do

        {

        scanf("%d%d%d", &a.day,&a.month, &a.year);

        }

while(TestData(&a)==0);

PlusData(&a,17);

}

//--------------------------------------------------------

     Фактически определение класса объектов кактипа данных и известного набора функций для выполнения операций  над переменнымиэтого  типаэквивалентно понятию базового типа данных (БТД) языка программирования. Единственное отличие класса от БТД заключается в том,  чтопервый определяется программистом, а второй встроен в определение языка программирования.

     Язык программирования  Си++ представляет  собой  расширениеязыка Си для программирования объектови  их классов.  При  этом использованиеклассов эквивалентно вплоть до синтаксиса использованию базовых типов данных:

   Понятия классического  Си      Понятия Си++

   -------------------------       — БТД:                             Класс:

элементданных языка, для        определяемаяпользователем

которогоизвестно множество      структура,элементы которой

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

                                и множествафункций, оперирующих с ним.

— Переменная:                      Объект:

 область памяти, содержащая      переменная, содержащая

 структуру данных определенного  структуру данных, определенную

 типа.                            как класс.

— Операция:                       Переопределение операторов:

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

 БТД, к которому относится пере-  вызвана в виде одной из стандарт менная (такоперация '+'         ных операций языкаСи, которая

 по-разному интерпретируется для  переопределяется, если операндом

 переменных типа int и double).   ее является объект класса, а не

                                  переменнаяБТД.

    

        Лекция 2. Дополнительные возможностиязыка  Си++

       -----------------------------------------------

     Ниже рассмотрим средства,  расширяющие классический Си. Хотя

они и неотносятся непосредственно к классам,  сих помощью можно

реализоватьрассмотренные выше принципы объектно-ориентированного

программирования.

     2.1. Присваивание структур

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

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

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

структурыбез ключевого слова struct.

structdat

        { int  day,month,year; }

dat     NextDat(dat x)     // Формальный параметр — структура

{...   return(x);   }    // Возвратить структуру как результат

dat     Nextdat1(dat *p)

{...   return(*p);  }    // Возврат структуры косвенно по ссылке

dat     a,b,c,*q;          // Ключевое слово struct неиспользуется

void    main()

{

q =&b;

a =b;                     // Прямоеприсваивание структур

a =*q;                    // Косвенноеприсваивание по ссылке

c =NextDat(b);            // Присваиваниеструктуры как результата

c =NextDat1(&b);          // функции,фактический параметр в

}                          // NextDat — копияструктуры

     2.2. Обращения по адресу (неявная ссылка)

     ----------------------------------------

     При работе со структурами большого размера- при передаче их

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

Си++                            Эквивалент в«классическом» Си

------------------------       -----------------------------//--------------- Инициализацияконстантой  -----------------int     &a = 5;                 int     a, *pa =a;

                                *pa = 5;

//---------------Инициализация переменной -----------------int     x;                      int     x,*pa;

int     &a = x;                 pa = &x;

a =5;                          *pa = 5;

//--------------Неявная ссылка на структуру ----------------struct  dat                     struct dat

{ intday,month,year };         { intday,month, year };

dat  x;                         dat  x;

dat&b = x;                     dat* pb =&x;

dat&c = {12,12,1990};          dat  cc = {12,12,1990};

                                dat *pc =&cc;

b.year =1990;                  pb->year= 1990;

c.day=b.day+3;                  pc->day = pb->day+3;

c =b;          // Копирование  pc->day = pb->day;

                // структуры    pc->month = pb->month;

                               pc->year  = pb->year;

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

параметрами- обычными значениями и неявными ссылками — синтаксически идентичен. То жесамое касается результатов.

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

     — значением;

     — явной ссылкой;

     — неявной ссылкой.

Пример1.               Параметры — значения

---------------------------------------------------------dat     Inc(dat x)      ========> — копирование

{                       --------> — ссылка

x.day++;

return(x);              ----¬   стек +---+x.day++

}                       ¦ b =========> x=========¬

                        L----        +---+        ¦ return(x)

void    main()                                    ¦

{                       ----¬   стек +---+      --¦-¬ временная

dat     a,b,*p;         ¦ a <========= x <=======   ¦ переменная

a =Inc(Inc(b));        L----        +---+      L---p = &Inc(b);                              x.day++

a = *p;

}

Пример2.               Параметры — явные ссылки

---------------------------------------------------------dat*    Inc(dat* x)            x->day++

{                              x->day++

x->day++;                       ----¬   стек +---+

return(x);                 г===== b < — x ¦

}                          ¦  -->  <----¬   +-¦-+

                           ¦  ¦ L----   ¦     ¦return(x)

                           ¦  ¦  г======+=====void    main()        a=*..¦ ¦   ¦      ¦  +---+ стек

{                          ¦  ¦ --¦-¬   L---- x ¦

dat     a,b,*p;            ¦ ¦ ¦   =========>   ¦

a =*Inc(Inc(&b));         ¦  ¦ L----       +-¦-+

p =Inc(&b);               ¦  ¦ ----¬          ¦return(x)

a =*p;                    ¦  L-- <===========}                         ¦    L---                           ¦    ----¬

                           L====> a ¦

                                L---

Пример3.               Параметры — неявныессылки

---------------------------------------------------------dat&    Inc(dat& x)            x.day++    неявная ссылка dat* px

{                              x.day++

x.day++;                        ----¬   стек +---+

return(x);                 г===== b < — px¦

}                          ¦  -->  <----¬   +-¦-+

                           ¦  ¦ L----   ¦     ¦return(px)

                           ¦  ¦  г======+=====void    main()        a=*..¦ ¦   ¦      ¦  +---+ стек

{                          ¦  ¦ --¦-¬   L---- px¦

dat     a,b,*p;            ¦ ¦ ¦   =========>   ¦

a =Inc(Inc(b));           ¦  ¦ L----       +-¦-+

p =&Inc(b);               ¦  ¦ ----¬          ¦return(px)

a =*p;                    ¦  L-- <===========}                         ¦    L---                           ¦    ----¬

                           L====> a ¦

                                L---

     Сравнение этих примеров показываетследующее:

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

     — при возвращении результата  используется имя  переменной, которая заменяетсятранслятором неявной ссылкой на нее;

     — примеры 2 и 3 идентичны пореализации,  но  отличаются посинтаксису вызова функции;

     — примеры 1 и 3 отличаются пореализации,  но  идентичны посинтаксису вызова функции;

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

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

     — при входе  в функцию в стекепредполагается существованиенеявного параметра — «длинной» ссылки  на структуру,  в  которой размещается результат функции;

     — при выполнении операции return(x), где x- локальная переменная или формальный параметр, выполняется побайтовое копирование переменной x по адресу, заданномунеявным параметром;

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

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

Программана Си++       Реализация

-----------------       ----------   — неявный параметр

dat     Inc(dat x)      void   Inc(dat *r,dat x)

{                       {

x.day++;                x.day++;

return(x);              *r = x;         // Копирование

}                       }               // результата

void    main()          void    main()

{                       {

dat     a,b*p;          dat     a,b,*p;

                        dat     t,u;   // Временнye переменнye

a =Inc(b);             Inc(&a,b);      // Ссылка на левую часть

p =&Inc(b);           Inc(&t,b);      // Присаиваниевременной

                        p = &t;         // переменной и получение

a =*p;                 a = *p;         // ссылки на нее

a =Inc(Inc(b));        Inc(&u,b);      // Промежуточный результат

                        Inc(&a,u);      // во временной переменной

}                       }

     2.3. Функции — элементы структуры

     --------------------------------     Повторим рассмотренный выше пример вдругой форме:

//------------структура dat — аналог класса объектов «дата» --struct dat

        {

        unsigned day;

        unsigned month;

        unsigned year;

        int    TestData();

        void   NextData();

        void   PlusData(int n)

                {

                while(n-- !=0)dat::NextData(this);

                }

        };

//-----------набор функций для класса объектов «дата» --------static  int    mm[] = {31,28,31,30,31,30,31,31,30,31,30,31};

//-----------Проверка  на корректность-----------------------int    dat::TestData()

{

if (month==2 && day==29 && year %4 ==0) return(1);

if (month==0 || month >12 || day ==0 || day >mm[month])

        return(0);

return(1);

}

//-----------Следующая дата ----------------------------------void    dat::NextData()

{

day++;

if (day<= mm[month]) return;

if (month==2 && day==29 && year %4 ==0) return;

day=1;

month++;

if (month!=13) return;

month=1;

year++;

}

//---------Основная программа --------------------------------void    main()

{

dat a;

do

        {

        scanf("%d%d%d", &a.day,&a.month, &a.year);

        }

while(a.TestData()==0);

a.PlusData(17);

}

//-------------------------------------------------------     Как видно из примера,  в качестве элементовструктуры могут

выступатьфункции. Такие элементы-функции имеют следующие особенности:

     — тело функции  может быть  определено  в самой  структуре(функция PlusData).В этом случае функция имеет стандартный вид;

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

имеет вид

        <имя структуры>::<имяфункции>

     — в теле фукции неявно определен один формальный параметр с

именемthis — ссылка на структуру, для которой вызывается функция

(В нашемпримере это будет struct dat *this ). Поля этой структуры доступны через явноеиспользование этой ссылки

        this->month = 5;

        this->day++;

илинеявно

        month = 5;

        day++;

     — для переменной,  имеющей тип некоторой  структуры,  вызов

функцииэлементаэтой структуры имеет вид

        <имя переменной>.<имяфункции> ( <список параметров> )

     2.4. Переопределение функций

     ---------------------------     В Си++ возможно определение нескольких функций с одинаковым

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

словомoverload:

overload        SetDat;

void    SetDat(int dd,int mm,int yy,dat *p)

        {                    // Дата вводится в видетрех целых

        p->day=dd;

        p->month=mm;

        p->year=yy;

        }

void    SetDat(char *s,dat *p)  // Дата вводится в виде строки

        {

        sscanf(s,"%d%d%d",&p->day, &p->month, &p->year);

        }

void    main()

        {

        dat    a,b;

        SetDat(12, 12, 1990, &a);       // Вызов первой функции

        SetDat(«12,12,1990»,&b);       // Вызов второй функции

        }

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

struct  dat

        {

        int    day,month,year;

        void   SetDat(int,int,int);

        void   Setdat(char *);

        }

void    dat::SetDat(int dd,int mm,int yy)

        {

        day=dd; month=mm; year=yy;

        }

void    dat::SetDat(char *s)

        {

       sscanf(s,"%d%d%d",&day,&month,&year);

        }

void    main()

        {

        dat    a,b;

        a.SetDat(12,12,1990);

        b.SetDat(«12,12,1990»);

        }

     2.5. Операторы управления динамическойпамятью

    ---------------------------------------------

     В библиотеке  Си имеются две функции управлениядинамическойпамятью — malloc() и free(), которые выделяют и освобождают область  памяти заданного размера(в байтах).  В этой области программаможет разместить переменную (или массив), которая  называется динамической.При выделении памяти под динамическую переменную необходимо при помощи операцииsizeof  определять  количество байтов,  необходимое для размещенияпеременной указанного типа. В Си++введены два оператора,  аналогичныефункциям malloc и free new и delete.  Ониотличаются от соответствующих функций тем, что допускают использования  в  качестве аргументов  непосредственноспецификацию типа создаваемой динамическойпеременной и ссылки на динамическуюпеременную:

Си++                        «Классический» Си

-------------------------    ---------------------------------char    *s,x[80];             char    *s,x[80];

dat     *p,*q;                struct dat *p,*q;

void    main()                void main()

{                             {

p = newdat;                  p = malloc(sizeof(struct dat));

q = newdat[15];              q =malloc(15*sizeof (struct dat));

gets(x);                      gets(x);

s = newchar[strlen(x)+1];    s =malloc(strlen(x)+1);

...                           ...

delete  p;                    free(p);

delete  q;                    free(q);

delete  s;                    free(s);

}

     Операторы имеют вид:

<результат:ссылка на           <абстрактный

динамическуюпеременную>  new   описатель типа>

                        delete  <ссылка на динамическую

                                переменную>

     2.6. Параметры функций по умолчанию

     ----------------------------------

     При определении  формальных параметров  функции  может быть

указаноего значение,  принимаемое привызове  по  умолчанию при

отсутствииэтого параметра в списке фактических:

//-----Функция устанавливает по умолчанию текущее значение года,

//-----месяца и дня

#include<dos.h>

void    dat::SetDat(int d=0, int m=0, int y=0)

{

struct  date x;

getdate(&x);            // Стандартная функция получения

                        // текущей даты

                        // Проверка на значениепо умолчанию

year = (y== 0)? x.da_year: y;

month= (m== 0)? x.da_month: m;

day  = (d == 0)? x.da_day  : d;

}

     2.7 Контроль преобразования типов ссылок

     ---------------------------------------

     В «классическом»  Си  привыполнении присваивания,  передачефактическихпараметров происходит автоматическое  преобразованиессылок к базовым типам данных (int,unsigned) инаоборот,  а также преобразование одного типа ссылки к другому.  В Си++ такие «вольности» исключены,программист должен сам выполнить явное преобразование.  Например, при использовании функциираспределения динамической памяти, имеющей прототип в «alloc.h»

        extern void*    malloc(int n);

        dat    *p;

        p = (dat *) malloc (10*sizeof(dat));

                ¦

                L--- преобразование void*  в dat*

     Естественно, что  это преобразование  типов фиктивное втомсмысле,  что не меняет значения ссылки и не приводитк  генерации кода.  Оно  только меняет  «точку  зрения» транслятора на данную ссылку.

     2.8 Вставляемые (inline) функции

     -------------------------------

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

        struct dat

        {

        int    d,m,y;

        void   Setdat(char *p)  // Функция inlineпо умолчанию

                {

                ...              // Тело функции

                }

     2.9 Ссылки на элементы структуры

     -------------------------------

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

изпримера:

struct  dat

        {

        int    day,month,year;

        void   Getdat();

        void   Putdat();

        void   Nextdat();

        }

int     dat::*p;          // Ссылка на элемент типа int

                          // в структуре dat

p = &dat::month;         // Значение p — смещение (адрес)

                          // элемента month вструктуре типа

                          // dat

dat     x,*px = &x;       //

x.*p =5;                 // Обращение повнутренней ссылке

px->*p= 5;               //   . *<ссылка на элемент>

                          // <*dat>->*<ссылка на элемент>

Эквивалентно

x.month =5;

px->month=5;

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

должныбыть идентичными по результатам и параметрам:

void    (dat::*fun)();          // Ссылка на элемент-функцию

                                // структурыdat

fun =& dat::Putdat();          // Значениеfun — ссылка на

                                //элемент-функцию Putdat в dat

(x.*fun)();                     // Вызов элемента-функциипо

(px->*fun)();                   // ссылке fun для структурыx

                                // и дляструктуры по ссылке px

Эквивалентно

x.Putdat();

px->Putdat();

     2.10 Неизменяемые переменные (константы)

     ---------------------------------------

     В Си++ введен дополнительный контроль заизменением значенийпеременных. Ключевое слово const, используемой при определении и инициализации переменной, запрещает ее изменение, чтоконтролируется транслятором при ее дальнейшем использовании.  Такая же возможность  существует и для формальных параметров функции,  например:

const   int    n=5;

        n++;                    // Запрещено

int     xxx(const int m)

        {

        m++;                    // Запрещено

        }

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

     — при использовании conts применительно к указуемому значению разрешаетсямодифицировать саму ссылку при помощи присваивания и операций адресной арифметики, а изменения операндакосвеннопо ссылке запрещены.  Такая ссылканазывается ссылкой на постоянный объект:

        const char * p;

        p = «1234567890»;  // Разрешено присваивание ссылке

        p + =3;            // Разрешена модификация ссылки

        *(p+3) = '3';      // Запрещено присваивание по ссылке

        (*p)++;            // Запрещен инкремент по ссылке

     — при использовании const применительно кссылке запрещаетсяменять значение ссылки после инициализации, в томчисле средствами адресной арифметики. Такая ссылка называется постоянной ссылкой на объект:

        char const* p = «1234567890»;

        char   c;

        (*p) = '3';       // Разрешено присваивание по ссылке

        p++;             // Запрещено изменениезначен

еще рефераты
Еще работы по программированию, базе данных