МЕНЮ


Фестивали и конкурсы
Семинары
Издания
О МОДНТ
Приглашения
Поздравляем

НАУЧНЫЕ РАБОТЫ


  • Инновационный менеджмент
  • Инвестиции
  • ИГП
  • Земельное право
  • Журналистика
  • Жилищное право
  • Радиоэлектроника
  • Психология
  • Программирование и комп-ры
  • Предпринимательство
  • Право
  • Политология
  • Полиграфия
  • Педагогика
  • Оккультизм и уфология
  • Начертательная геометрия
  • Бухучет управленчучет
  • Биология
  • Бизнес-план
  • Безопасность жизнедеятельности
  • Банковское дело
  • АХД экпред финансы предприятий
  • Аудит
  • Ветеринария
  • Валютные отношения
  • Бухгалтерский учет и аудит
  • Ботаника и сельское хозяйство
  • Биржевое дело
  • Банковское дело
  • Астрономия
  • Архитектура
  • Арбитражный процесс
  • Безопасность жизнедеятельности
  • Административное право
  • Авиация и космонавтика
  • Кулинария
  • Наука и техника
  • Криминология
  • Криминалистика
  • Косметология
  • Коммуникации и связь
  • Кибернетика
  • Исторические личности
  • Информатика
  • Инвестиции
  • по Зоология
  • Журналистика
  • Карта сайта
  • Объективное программирование

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

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

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

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

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

    программирование:

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

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

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

    goto).

    Язык Паскаль - соответствует указанным принципам и был разработан под

    влиянием идей структурного программирования.

    Альтернативный подход - восходящее программирование - предполагает в

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

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

    Пример традиционного подхода библиотека стандартных функций.

    Следующий шаг - введение в программу объектов. Под объектом

    понимается структура данных, которая содержит полную информацию о состоянии

    соответствующего физического объекта, который отображается программой. В

    Си этому может соответствовать структура struct), в Паскале - запись

    (record). Множество объектов одного типа составляют понятие класса.

    Объектно-ориентированный подход к разработке программ предполагает, что в

    программе устанавливается взаимно-однозначное соответствие между

    физическими объектами,

    отображаемыми программой, и програмнными объектами, являющимися, по

    существу, структурированными переменными (в дальнейшем под термином

    "объект" будем понимать программный объект).

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

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

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

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

    помощи которых (а точнее, исключительно через которые)над объектом

    выполняется некоторое допустимое множество операций.

    Такие функции должны иметь обязательный параметр - ссылку на текущий

    объект, для которого они вызываются. Сами функции являются неотъемлимой

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

    действия над объектами одного и того же типа (то есть класса).

    Объектно-ориентированные программы можно разрабатывать и с помощью

    традиционных языков программирования. Рассмотрим пример определения

    объектов типа "дата" на классическом Си.

    //------ структура dat - аналог класса объектов "дата" --------typedef

    struct dat

    {

    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;

    //------ Следующая дата ----------------------------------------void

    NextData(p)

    DAT *p;

    {

    p->day++;

    if (p->day 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);

    }

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

    void main()

    {

    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.

    struct dat

    { 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

    { int day,month,year }; { int day,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 day++

    { x->day++

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

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

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

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

    a = *p; ¦ L-- a ¦

    L---

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

    ---------------------------------------------------------dat& Inc(dat&

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

    { x.day++

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

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

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

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

    a = *p; ¦ L-- a ¦

    L---

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

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

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

    переменной, которая заменяется транслятором на косвенное обращение по

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

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

    заменяется транслятором неявной ссылкой на нее;

    - примеры 2 и 3 идентичны по реализации, но отличаются по

    синтаксису вызова функции;

    - примеры 1 и 3 отличаются по реализации, но идентичны по

    синтаксису вызова функции;

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

    параметров недостаточен для определения транслятором способа их передачи

    (значением или ссылкой), поэтому в Си++ для каждой внешней функции

    необходимо задать прототип.

    Так как размер структуры, передаваемой в качестве результата функции,

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

    временную переменную. Транслятор "Borland C" в этом случае поступает

    следующим образом:

    - при входе в функцию в стеке предполагается существование неявного

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

    результат функции;

    - при выполнении операции 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()

    //----------- Следующая дата ----------------------------------void

    dat::NextData()

    {

    day++;

    if (day ::

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

    именем 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

    определять количество байтов, необходимое для размещения переменной

    Страницы: 1, 2, 3, 4, 5


    Приглашения

    09.12.2013 - 16.12.2013

    Международный конкурс хореографического искусства в рамках Международного фестиваля искусств «РОЖДЕСТВЕНСКАЯ АНДОРРА»

    09.12.2013 - 16.12.2013

    Международный конкурс хорового искусства в АНДОРРЕ «РОЖДЕСТВЕНСКАЯ АНДОРРА»




    Copyright © 2012 г.
    При использовании материалов - ссылка на сайт обязательна.