1 / 63

Объектно-ориентированное программирование (5 часов)

Объектно-ориентированное программирование (5 часов). Основные вопросы. Основные понятия объектно-ориентированного программирования Объектно-ориентированное программирование на C++ Дополнительные средства создания классов в С++ Множественное наследование Шаблоны классов. Поколения языков.

Télécharger la présentation

Объектно-ориентированное программирование (5 часов)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Объектно-ориентированное программирование(5 часов)

  2. Основные вопросы • Основные понятия объектно-ориентированного программирования • Объектно-ориентированное программирование на C++ • Дополнительные средства создания классов в С++ • Множественное наследование • Шаблоны классов

  3. Поколения языков • Первое поколение- языки с минимальными возможностями типизации • Предоставляют лишь средства для описания переменных простых типов и массивов; никаких новых типов вводить нельзя. • Фортран, Алгол-60. • Второе поколение – языки, предоставляющие программисту основные конструкторы типов: массивы, записи, объединения • ПЛ/1, Алгол-68, Паскаль, С • Тип рассматривается как множество значений, получаемых из базисных множеств с помощью конструкторов. • Все операции над типами данных предопределенные — определяемые языком, а не программистом. • Новые типы могут получать имена, но с ними нельзя связывать новых, специально вводимых операций. • Третье поколение– языки, предоставляющие программисту средства определения абстрактных типов данных • С++, C#, Java • Типы понимаются как множества с операциями.

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

  5. Определение абстрактного типа данных • Абстрактный тип данных — это способ определения некоторого понятия в виде класса объектов с некоторыми свойствами и операциями. • Так как свойства обычно выражаются в терминах операций, то абстрактный тип данных часто отождествляют с соответствующим множеством операций. • Например: • определение понятия стека в терминах операций "втолкнуть элемент в стек", "создать новый стек", "выдать верхний элемент" и т.д. • В языке программирования такое определение оформляется как специальная синтаксическая конструкция, называемая в разных языках капсулой, модулем, кластером, классом, пакетом, формой и т.д. • Понятие абстрактного типа данных — это, по существу, аналог определения в математике, где новые понятия образуются из некоторых исходных объединением их в одно целое, имеющее новый статус, новое имя.

  6. Объектно-ориентированное программирование • Идея абстрактных типов данных является основой объектно-ориентированного программирования (ООП). • Основные принципы ООП были разработаны еще в языках Simula-67 и Smaltalk, но в то время не получили распространения из-за сложности освоения и низкой эффективности реализации. • В С++ концепции ООП реализованы эффективно и непротиворечиво, что явилось основой успешного распространения как языка, так и концепции ООП. • ООП – не просто набор новых средств, добавленных в язык • Например, на С++ можно писать программы и без использования ООП, и наоборот, можно написать объектную по сути программу на языке не содержащим специальных средств поддержки объектов. • ООП – новая парадигма программирования

  7. Понятие парадигмы ООП • Термин «парадигма» - означает набор теорий, стандартов и методов, которые совместно представляют собой способ организации знаний, способ видения мира. • В программировании этот термин используется для определения модели вычислений, т.е. способа структурирования информации, организации вычислений и данных. • Объектно-ориентированная программа строится в терминах объектов и их взаимосвязей.

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

  9. Выбор степени абстракции • Выбор степени абстракции определяется типом задачи, которую требуется решить. • Не имеет смысла использовать сложные технологии для решения простых задач, но попытка «по-простому» справиться со сложной проблемой обречена на провал. • Еще одной проблемой является то, что сложные технологии требуют больших затрат времени на освоение.

  10. Основные свойства ООП • Инкапсуляция • Наследование • Полиморфизм

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

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

  13. Пример иерархии типов данных Опер Аналитик Начальник МО ФСБ Пенсионер Военнослужащий Гражданин

  14. Полиморфизм • Полиморфизм – свойство объекта принадлежать одновременно к нескольким типам данных иерархии. • Полиморфизм дает возможность использовать в различных классах иерархии одно и то же имя для обозначения сходных по смыслу действий, т.е. одни и те же методы могут быть реализованы на различных уровнях иерархии по-разному.

  15. Пример полиморфизма Опер Аналитик Начальник Сотрудник МО Сотрудник ФСБ Пенсионер Военнослужащий Гражданин Объявим переменную X типа «Аналитик». Объект X является как экземпляром класса «Аналитик» так и экземпляром классов «Сотрудник ФСБ», «Военнослужащий», «Гражданин»

  16. Наследование и агрегация • Агрегация - включение существующих типов данных во вновь создаваемый в качестве составных элементов. • Важно не путать агрегацию и наследование. • Агрегация не создает иерархии и не допускает полиморфизма Сотрудник ФСБ Военнослужащий Дата ДЕНЬ - целое МЕСЯЦ - целое ГОД - целое

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

  18. ООП в С++ • Абстрактные типы данных в С++ создаются с помощи синтаксической конструкции называемой «классом». • Классы позволяют программисту на С++ воспользоваться всеми свойствами ООП (инкапсуляция, наследование и полиморфизм)

  19. Инкапсуляция в С++ • Спецификация класса в С++ class имя_класса{ модификатор_доступа: [атрибуты] [методы] модификатор_доступа: [атрибуты] [методы] … }; • Модификаторы доступа • private • public • protected

  20. Пример использования класса для реализации понятия даты class date{ private: int month, day, year; public: void set(int, int, int); void get(int*, int*, int*); void next(); void print(); };

  21. Простое наследование в C++ • При описании класса в его заголовке указывается класс, являющийся для него базовым. • Возможность обращения к элементам этого класса регулируется с помощью ключей доступа private, protected и public class имя: [private|protected|public] базовый_класс { тело класса }; • По умолчанию для классов используется ключ доступа private • Простым называется наследование, при котором производный класс имеет одного родителя.

  22. Доступ к элементам базового класса

  23. Пример простого наследования classdate{ private: intmonth, day, year; public: voidset(int, int, int); voidget(int*, int*, int*); voidnext(); voidprint(); }; … date d; d.day = 15; // Ошибка! d.set(2006,1,1); d.print(); date *pd = new date; pd->set(2006,1,1); pd->print(); delete pd;

  24. class datetime:publicdate{ private: int hour, min, sec; public: void setAll(int, int, int, int, int, int); void getAll(int*, int*, int*, int*, int*, int*); void setTime(int, int, int); void getTime(int*, int*, int*); void printAll(){ … printf(“%i”,day); // Ошибка print(); // Правильно } void printTime(); }; … datetime dt; dt.set(2006,1,1); dt.setAll(2006,1,1,10,30,00); dt.printAll(); dt.printTime(); dt.print(); datetime *pdt = new datetime; pdt->set(2006,1,1); pdt->setAll(2006,1,1,10,30,00); pdt->printAll(); pdt->printTime(); pdt->print();

  25. class datetime:privatedate{ private: int hour, min, sec; public: void setAll(int, int, int, int, int, int); void getAll(int*, int*, int*, int*, int*, int*); void setTime(int, int, int); void getTime(int*, int*, int*); void printAll(); void printTime(); }; … datetime dt; dt.set(2006,1,1); // Ошибка!! dt.setAll(2006,1,1,10,30,00); dt.printAll(); dt.printTime(); dt.print(); // Ошибка!! datetime *pdt = new datetime; pdt->set(2006,1,1);// Ошибка!! pdt->setAll(2006,1,1,10,30,00); pdt->printAll(); pdt->printTime(); pdt->print();// Ошибка!!

  26. Наследование и конструкторы • Конструкторы не наследуются, поэтому производный класс должен иметь собственные конструкторы. Порядок вызова конструкторов определяется приведенными ниже правилами. • Если в конструкторе производного класса явный вызов конструктора базового класса отсутствует, автоматически вызывается конструктор базового класса по умолчанию (то есть тот, который можно вызвать без параметров). • Для иерархии, состоящей из нескольких уровней, конструкторы базовых классов вызываются начиная с самого верхнего уровня. После этого выполняются конструкторы тех элементов класса, которые являются объектами, в порядке их объявления в классе, а затем исполняется конструктор класса.

  27. Пример вызовов конструкторов (1) Классы А, B, C и D образуют иерархию Классы X, Y, Z самостоятельные C D Z X B Y Y Z A X Предположим, что класс A содержит в себе экземпляр класса X, класс B – экземпляр класса Y, класс C экземпляр класса Z. Все классы имеют конструкторы по умолчанию.

  28. Пример вызовов конструкторов (2) class A { public: A(); X x; … }; class B : public A { public: B(); Y y; … }; class C : public B { public: C(); Z z; … }; class D : public B { public: D(); … }; class X { public: X(); … }; class Y { public: Y(); … }; class Z { public: Z(); … };

  29. Пример вызовов конструкторов (3) При создании экземпляра класса С вызов конструкторов будет происходить в следующей последовательности: С с; или С *с = new C; • Вызывается конструктор класса С. • Вызывается конструктор класса B. • Вызывается конструктор класса А. • Вызывается конструктор для класса X. • Выполняется тело конструктора А. • Вызывается конструктор класса Y. • Выполняется тело конструктора B. • Вызывается конструктор класса Z. • Выполняется тело конструктора C.

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

  31. Последовательность вызовов деструкторовпри вызовеdelete c; • Если в классе С определен деструктор, то выполняется его тело. • Выполняется деструктор для объекта z. • Выполняется деструктор для базового класса B • Если в классе B определен деструктор, то выполняется его тело. • Выполняется деструктор для объекта Y. • Выполняется деструктор для базового класса A. • Если в классе A определен деструктор, то выполняется его тело. • Выполняется деструктор для объекта X.

  32. Операция присваивания • Операция присваивания не наследуется. • Требуется явное определение операции присваивания в производном классе.

  33. Пример использования операции присваивания (1) class man{ private: char *fio; … public: const man & operator=(man &m){ if(fio != NULL) delete [] fio; if(m.fio != NULL){ fio = new char[strlen(m.fio)+1]; strcpy(fio,m.fio); } else fio = NULL; return *this; } };

  34. Пример использования операции присваивания (2) class business_man: public man{ private: unsigned long int many; … public: const business_man & operator=(business_man &m){ many = m.many; man::operator=(m); return *this; } };

  35. Полиморфизм и виртуальные методы (1) • Работа с объектами чаще всего производится через указатели. • Благодаря свойству полиморфизма указателю на базовый класс можно присвоить значение адреса объекта любого производного класса. • Например: class A {}; class B : public A{}; A *pointer; pointer = new B;

  36. Полиморфизм и виртуальные методы (2) • В каждом из классов опишем по методу с одинаковым названием. class A { public: void metod1(); … }; class B : public A{ public: void metod1(); … }; Вызов методов объекта происходит в соответствии с типом указателя, а не фактическим типом объекта, на который он ссылается, поэтому при выполнении оператора, например, A *pointer = new B; pointer->metod1(); будет вызван метод класса A, а не класса B, поскольку ссылки на методы разрешаются во время компоновки программы. Этот процесс называется раннимсвязыванием.

  37. Полиморфизм и виртуальные методы (3) Чтобы вызвать метод класса B, можно использовать явное преобразование типа указателя: ((B *)pointer)->metod1(); Это не всегда возможно, поскольку в разное время указатель может ссылаться на объекты разных классов иерархии, и во время компиляции программы конкретный класс может быть неизвестен. Например: • Функция, параметром которой является указатель на объект базового класса. На его место во время выполнения программы может быть передан указатель на любой производный класс. • Связный список указателей на различные объекты иерархии, с которым требуется работать единообразно.

  38. Полиморфизм и виртуальные методы (4) • В C++ реализован механизм позднего связывания, когда разрешение ссылок на метод происходит на этапе выполнения программы в зависимости от конкретного типа объекта, вызвавшего метод. • Этот механизм реализован с помощью виртуальных методов. • Виртуальнымназывается метод, ссылка на который разрешается на этапе выполнения программы.

  39. Виртуальные методы • Для определения виртуального метода используется спецификатор virtual, например: class A { public: virtualvoid metod1(); … }; class B : public A{ public: virtualvoid metod1(); … };

  40. Правила описания и использования виртуальных методов (1) • Если в базовом классе метод определен как виртуальный, метод, определенный в производном классе с тем же именем и набором параметров, автоматически становится виртуальным, а с отличающимся набором параметров — обычным. class A { public: virtualvoid metod1(); … }; class B : public A{ public: void metod1(); // виртуальный метод void metod1(int a);// обычный метод … };

  41. Правила описания и использования виртуальных методов (2) • Виртуальные методы наследуются, то есть переопределять их в производном классе требуется только при необходимости задать отличающиеся действия. Права доступа при переопределении изменить нельзя. class A { public: virtualvoid metod1(); … }; class B : public A{ public: … }; A *pointer = new B; pointer->metod1(); // допустимая операция будет вызван // метод класса A

  42. Правила описания и использования виртуальных методов (3) • Если виртуальный метод переопределен в производном классе, объекты этого класса могут получить доступ к методу базового класса с помощью операции доступа к области видимости. class A { public: virtualvoid metod1(); … }; class B : public A{ public: void metod1(){ … A::metod1(); … } … }; A *pointer = new B; pointer->metod1();

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

  44. Абстрактные классы и чисто виртуальные методы • При описании класса можно описать виртуальный метод у которого нет реализации в данном классе. Для этого используется специальный синтаксис. class A { public: virtualvoid metod1()= 0; … }; • Такой метод называется чисто виртуальным. • Класс, содержащий хотя бы один чисто виртуальный метод, называется абстрактным. • Абстрактные классы предназначены для представления общих понятий, которые предполагается конкретизировать в производных классах. • Абстрактный класс может использоваться только в качестве базового для других классов — объекты абстрактного класса создавать нельзя, поскольку прямой или косвенный вызов чисто виртуального метода приводит к ошибке при выполнении.

  45. Правила использования абстрактных классов • Абстрактный класс нельзя использовать при явном приведении типов, для описания типа параметра и типа возвращаемого функцией значения • Допускается объявлять указатели и ссылки на абстрактный класс, если при инициализации не требуется создавать временный объект • Если класс, производный от абстрактного, не определяет все чисто виртуальные функции, он также является абстрактным • Можно создать функцию, параметром которой является указатель на абстрактный класс. На место этого параметра при выполнении программы может передаваться указатель на объект любого производного класса

  46. Пример использования абстрактных классов class Figure { public: virtual void draw()= 0; … }; class Triangle : public Figure{ public: virtualvoid draw(); … }; class Square : public Figure{ public: virtualvoid draw(); … }; Figure *mas[2]; mas[0] = new Triangle(); mas[1] = new Square(); for(inti=0;i<2;i++) mas[i]->draw();

  47. Множественноенаследование • Множественное наследование означает, что класс имеет несколько базовых классов. • Множественное наследование применяется для того, чтобы обеспечить производный класс свойствами двух или более базовых. • Чаще всего один из этих классов является основным, а другие обеспечивают некоторые дополнительные свойства, поэтому они называются классами подмешивания.

  48. Иерархия классов при множественном наследовании Бобер Летучая рыба Обитатель суши Обитатель воды Обитатель воздуха Утка

  49. Синтаксис множественного наследования class имя: [private|protected|public] базовый_класс1, [private|protected|public] базовый_класс2, … { тело класса };

  50. Пример множественного наследования class clX { public: clX(); int ValueX; … }; class clY { public: clY(); bool ValueY; … }; class clZ: public clX, public clY{ public: clZ(); double ValueZ; … }; … clZ *z = new clZ; z->ValueX = 10; z->ValueY = true; z->ValueZ = 5.7; … delete z;

More Related