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

Парадигмы программирования

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

  • императивное (процедурное)

    • операциональное (ассемблер, фортран, basic);

    • структурное (Pascal, Modula);

  • непроцедурное:

    • декларативное;

      • функциональное(Lisp, Haskell);

      • логическое (Prolog);

  • объектное (объектно-ориентированное) (C++, SmallTalk, Delphi, VB).

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

Объектное (объектно-ориентированное) программирование – парадигма программирования, в которой основными концепциями являются понятия объектов и классов. В ООП все (процессы, данные, события) является объектами. Все объекты располагают собственными данными, представленными как ссылки на другие объекты. Объекты могут обмениваться между собой сообщениями. При получении объектом сообщения запускается соответствующий ему обработчик, иначе называемый методом. У объекта есть объект-предок. Если метод для обработки сообщения не найден, сообщение будет перенаправлено объекту-предку. Эту структуру в целом (таблица обработчиков + предки) выделяют в класс объекта. У самого объекта будет ссылка на объект, представляющий его класс. Объект по отношению к своему классу является экземпляром. Так как классы тоже представлены, как объекты, существует класс, определяющий поведение, общее для всех классов. Такой класс принято называть метаклассом.

  1. Объекты не могут непосредственно работать с собственными данными других объектов и не могут нарушить их внутреннюю согласованность. Это свойство (сокрытие данных) принято называть инкапсуляцией.

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

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

Отношение "потомок-предок" на классах принято называть наследованием.

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

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

Функциональное программирование обладает следующими двумя примечательными свойствами:

  1. аппликативность: программа есть выражение, составленное из применения функций к аргументам;

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

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

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

Организация вычислений в языке функционального программирования

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

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

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

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

  • краткость и простота – программы на функциональных языках обычно намного короче и проще, чем те же самые программы на императивных языка;

  • модульность – разделение программ на несколько сравнительно независимых частей (модулей) с чётко определёнными связями между ними;

  • функции — объекты вычисления;

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

  • о тложенные (ленивые) вычисления – какой-либо аргумент вычисляется, только если он нужен для вычисления результата.

Язык логического программирования Prolog

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

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

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

числа и строки такие же, как и в других языках;

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

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

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

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

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

book('Название','2009','Спб',authors('Первый автор','Второй автор')).

Еще одной конструкцией являются списки(либо пустой список, не содержащий не одного элемента, либо структура, имеющая два компонента : голову и хвост), элементы которых заключаются в квадратные скобки. В основе списков в Пролог лежат связные списки (List=[a, b,[c, d], e]).

Правила в Прологе записываются в форме правил логического вывода с логическими заключениями и списком логических условий (по форме «дизъюнктов Хорна» - утверждений вида A <= B1& ...&Bn): «Вывод:- Условие».

Факт констатирует, что между объектами выполнено некоторое отношение. Он состоит только из заголовка. Можно считать, что факт - это предложение, у которого тело пустое. Факт (аксиома)представляет собой безусловно истинное утверждение: «Кот(Иван)».

Пролог предусматривает возможность отсечения, которая используется для прерывания поиска с возвратом; отсечение обозначается восклицательным знаком (!). Действует отсечение просто: через него невозможно совершить откат (поиск с возвратом). Однажды пройдя через отсечение, уже невозможно произвести откат к подцелям.

Пример простейшей программы на Прологе:

member(X, [X|_]).

member(X, [_|T]) :- !, member(X, T).

Вычисления в Пролог осуществляются методом проб и ошибок (посредством поиска с возвратами). Базовым принципом языка является равнозначность представления программы и данных (декларативность).

Логическое программирование допускает естественную параллельную реализацию. В примере с предикатом member два правила для него могли применяться параллельно, образуя ИЛИ-систему процессов. ИЛИ-система успешно доказывается, если хотя бы 1 процесс в системе успешен.

Назначение функций С, форма описания функций, прототип функции, вызов функции. Передача параметров в функцию.

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

В ызывается функция по ее имени, при этом в качестве параметров указываются необходимые переменные или константы: pow(1.2, i). При вызове функции тип каждого фактического параметра сверяется с типом, указанным в описании функции, точно так же, как если бы инициализировалась переменная описанного типа. Это гарантирует надлежащую проверку и преобразования типов. Например, вызов функции pow(12.3,"abcd") транслятор сочтет ошибочным, поскольку "abcd" является строкой, а не параметром типа int. В вызове pow(2,i) транслятор преобразует целую константу (целое 2) в число с плавающей точкой (float), как того требует функция. Функция pow может быть определена следующим образом (рисунок).

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

Такое многократное использование имени называется перегрузкой имени функции или просто перегрузкой.

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

Унарная операция * называется косвенностью (или операцией разыменования), она выбирает значение объекта, на который настроен указатель.

Если использовать передачу параметра по ссылке, можно обойтись без явных операций с указателем (рисунок). Для любого типа T запись T& означает "ссылка на T". Ссылка служит синонимом той переменной, которой она инициализировалась. Отметим, что перегрузка допускает сосуществование двух функций swap в одной программе.

Динамическая память. Определение, назначение. Функции распределения памяти: malloc, calloc, free либо new и delete.

malloc

#include<stdlib.h>

#include<alloc.h>

Void *malloc(size_t size);

Функция обеспечивают выделение блока памяти, размером size байт. Функция возвращает указатель на первый байт выделенной памяти или нулевой указатель NULL, если для размещения блока недостаточно памяти. Содержимое блока остается неизменным. Если size=0, то функция возвращает NULL.

Char *realloc(char *ptr, unsigned size);

Функция realloc изменяет размер ранее захваченного блока памяти. Аргумент ptr указывает на начало блока. Аргумент size задает новый размер блока в байтах. Содержимое блока не изменяется. Функция realloc возвращает char-указатель на перезахваченный блок памяти или значение NULL, если памяти недостаточно, чтобы расширить блок к заданному размеру. Блок может быть передвинут, если его размеры изменены, поэтому аргумент ptr для функции realloc не обязательно такой же, как и возвращаемое значение. При возврате NULL первоначальный блок освобождается. В памяти, на которую указывает возвращаемое значение, гарантировано выравнивание для хранения любого типа объекта. Чтобы получить указатель на тип, отличный от char, используется преобразователь типа возвращаемого значения.

Void * calloc(size_t nitems, size_t size);

Функция calloc() выделяет память, размер которой равен значению выражения nitems * size, т.е. память, достаточную для размещения массива, содержащего nitems объектов размером size. Блок обнуляется. Если вы хотите выделить блок, размер которого превышает 64К то нужно использовать функцию farcalloc. calloc возвращает указатель на первый байт выделенной памяти или NULL, если недостаточно памяти для выделения нового блока или nitems или size равны 0.

Void free(void *ptr);

Функция free() возвращает в динамически распределяемую область памяти блок памяти, адресуемый указателем рtr, после чего эта память становится доступной для выделения в будущем. Указатель ptr должен указывать на первый байт выделенной ранее динамической памяти с помощью функций malloc, calloc или realloc. Использование недопустимого указателя при вызове может вызвать крах системы. При передаче нулевого указателя функция free() не выполняет никакого действия.

Оператор new выделяет динамическую память и возвращает указатель соответствующего типа на эту область памяти: Data *p_var = new Data;

Здесь p_var — это переменная указателя, которая будет принимать адрес выделенной памяти, а Data представляет собой тип данных, которые будут храниться в этой памяти. Если запрос на выделение памяти не удовлетворяется, возникает исключение bad_alloc.

Инициализировать выделенную память можно, задав инициализатор и использовав при этом следующую форму записи: Data *p_var = new Data (init);

init — это значение, которое будет присвоено выделенной памяти.

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

Data *p_var = new Data [size];

size указывает длину массива. При выделении массивов инициализация производиться.

Оператор delete освобождает память, на которую указывает аргумент. Эта память предварительно должна быть выделена с помощью оператора new: delete p_var;

Чтобы освободить массив, который был выделен с помощью оператора new, можно использовать следующую форму записи: delete [] p_var

Определение структуры (С). Описание и назначение структур. Массивы структур. Передача структуры в функцию.

Структура – тип данных, представляющий собой одну или несколько переменных различных типов, которые сгруппированы для удобства под одним именем. Пример структуры – учетная карточка работающего: "служащий", описывается набором атрибутов, таких, как фамилия, имя, отчество, адрес и т.д. Некоторые из этих атрибутов сами могут оказаться структурами (ФИО).

Структуры оказываются полезными при организации сложных данных особенно в больших программах, поскольку они позволяют сгруппировать связанные данные таким образом, что с ними можно обращаться, как с одним целым, а не как с отдельными объектами. Приведем пример структуры «Дата»:

struct date {

int day;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]