
- •1. Типи знань і методи їх представлення.
- •2. Парадигми імперативного стилю. Підтримка в мовах програмування. Парадигма процедурності.
- •3. Парадигма модульности (локализации).
- •4. Парадигма атд.
- •5. Парадигма ооп.
- •7. Ефективний доступ до членів класу. Дружні функції та дружні класи.
- •8. Конструкторы и деструкторы.
- •9. Инициализация полей класса. Статические члены класса.
- •10. Наследование классов. Конструкторы базового класса.
- •11. Обмеження доступу до базового класу.
- •12. Множинне наслідування.
- •13. Виртуальные базовые классы.
- •14. Конкретные и абстрактные типы. Виртуальные функции.
- •15. Виртуальные деструкторы и «витруальные» конструкторы. Клонирование.
- •16. Посилання. Ініціалізація, використання, порівняння з покажчиками.
- •17. Перевантаження функцій.
- •18. Перевантаження унарних операцій.
- •19. Перевантаження бінарних операцій.
- •20. Параметризація типів за допомогою шаблонів.
- •21. Параметризація функцій за допомогою шаблонів.
- •22. Перетворення за допомогою конструкторів. Обмеження.
- •23. Перетворення за допомогою перетворюючих функцій.
- •24. Область видимости.
- •25. Пространства имен. Директива using.
- •27. Потоки. Віртуальні операції введення та виведення.
- •29. Узагальнені алгоритми та бібліотека стандартних шаблонів. Ітератори.
14. Конкретные и абстрактные типы. Виртуальные функции.
Конкретный класс представляет собой относительно простое понятие со всеми операциями, существенными для поддержки этого понятия. В каждом из таких классов существует взаимооднозначное соответствие между интерфейсом и реализацией, ни один из этих классов не предназначен для создания производных классов. Конкретный тип напоминает встроенные типы, все встроенные типы – конкретные.
Класс, представляющий конкретный тип, предназначен для того, чтобы:
1. Точно соответствовать данному частному понятию и стратегии реализации.
2. Обеспечивать быстродействие и затраты памяти, сравнимые с «написанным вручную» кодом за счет применения встраивания и операций, полностью использующих особенности самого понятия и его реализации.
3. В минимальной степени зависеть от других классов.
4. Быть понятным и пригодным к использованию независимо от других классов.
Результат – тесная связь между пользовательским кодом и кодом реализации.
Пример: реализация стека. Требования: четкий интерфейс, запретить доступ к реальному стеку, инициализация.
// Интерфейс stack.h class stack {char *s; int top, size; public: char pop(); void push (char); stack (); //конструктор по умолчанию stack(int size);}; char stack::pop() {return s[top--];//стек увеличивается в обратном порядке};
Пример конкретного использования стека: void f(stack& stk) {stk.push(‘c’); if (stk.pop()!=’c’) Error(); }; // после изменения стека программу надо перекомпилировать.
Пример более абстрактного использования стека: class stack {public: virtual push(char)=0; virtual char pop()=0;//функции push и pop абстрактные, класс stack абстрактный }. Абстрактный класс позволяет не перекомпилировать исходный текст программ, который используют этот тип при изменении реализации типа.
Простейший способ ослабить связь между пользователями класса и его разработчиками, а также между создающим объекты кодом и кодом, пользующимся такими объектами, - ввести абстрактный класс, представляющий собой интерфейс ко множеству реализаций общего понятия. Абстрактные типы предназначены для того, чтобы:
1. Определить понятие таким образом, чтобы позволить сосуществовать в программе нескольким его реализациям;
2. Обеспечить приемлимое быстродействие и затраты памяти, благодаря использованию виртуальных функций;
3. Минимизировать зависимость каждой реализации от других классов.
Абстрактная реализация стека: class stack {public: virtual void push(char)=0; virtual char pop()=0;};
1. Это позволит не перекомпилировать исходный текст при изменении реализации типа.
2. Абстрактный тип требует, чтобы ниже в программе он был доопределен в каком-нибудь производном классе.
3. Для абстрактного класса нельзя описывать экземпляры: stack stk;//Err
void f(stack *stk) {stk->push(‘c’); if (stk->pop()!=’c’ Error…;} void main(){ Array_Stack(произв от stack класс) as [100]; f(as);…} class Array_Stack: public Stack {char *v; int top, stsize; public: … char pop(); void push(char);}; char Array_Stack::pop(){return v[top--];};
Абстрактные классы полезны при создании больших комплексов программ, т.к. они позволяют достигать независимости интерфейса от реализации. Они необходимы для того, чтобы достигнуть независимости некоторых модулей.
Вызов f(): void main(){ array_Stack as(100); f(as) …}; class array_Stack:public Stack {char *v; int size; public: … char pop(); void push(char);}; char array_Stack::pop() {return v[top--];}
Абстрактные классы полезны при создании больших комплексов программ, они позволяют проследить независимость интерфейса от реализации.
Виртуальные функции решают проблему, связанную с полем типа, предоставляя возможность программисту объявить в базовом классе функции, которые можно заместить в каждом производном классе. Компилятор и загрузчик гарантируют правильное соответствие между объектами и функциями, применяемыми к ним.
Class A {public: virtual void f(){cout<<”I’m A”;};} class B:public A {public: void f(){cout<<”I’m B”;};} void g() {A a; B b; a.f(); b.f(); g1(&a); g1(&b);} void g1(A *pa){pa->f();}
С каждым классом, который имеет виртуальные функции, связывается таблица виртуальных функций Vtbl. С каждым экземпляром класса связывается один указатель на его таблицу вирт фн. С прибавлением каждого экземпляра прибавляется дополнительное поле. Для каждого класса – одна общая таблица.
При использовании виртуальных функций необходимо оценить сложность и объем памяти. 1. Эффективность использования с точки зрения сложности (вычислительной). 2. Эффективность использования с точки зрения памяти.