- •Київський національний університет імені Тараса Шевченка
- •Гриф надано Міністерством освіти і науки України (лист № 1.4/18-г-1523 від 20.09.07)
- •Основи алгоритмізації
- •1.1. Поняття алгоритму
- •1.2. Класифікація внутрішніх структур алгоритмів
- •1. Ввести а,b.
- •3. Вивести значення s.
- •4. Кінець.
- •6. Закінчити роботу.
- •1. Ввести число n.
- •6. Перехід до п.3.
- •7. Друк к.
- •8. Кінець.
- •1.3. Складність алгоритмів
- •1.4. Складність задач
- •Завдання для самостійної роботи
- •Форма Бекуса – Наура
- •Завдання для самостійної роботи
- •Void main(){
- •3.2. Структура с-програми
- •3.3. Описувачі
- •3.4. Основні операції мови с
- •If(!inword)
- •Void main()
- •Int rozmir;
- •3.5. Оператори мови с
- •3.5.1. Прості оператори
- •3.5.2. Умовний оператор
- •3.5.3. Оператор циклу for
- •3.5.4. Оператори do-while, while
- •3.5.5. Оператор continue
- •3.5.6. Оператор-перемикач switch
- •3.5.7. Оператор break
- •3.5.8. Оператор goto
- •If(error(I,j,k)) goto exit;
- •3.5.9. Оператор return
- •3.6. Директиви препроцесору та вказівки компілятору
- •3.6.1. Директива препроцесору #define
- •1. Макровизначення:
- •3.6.3. Директива #include
- •3.6.4. Директиви умовної компіляції #if, #elif, #else, #endif
- •3.6.5. Директива #line
- •If(!cond)
- •3.7. Описувачі з модифікаторами
- •3.7.1. Моделі пам'яті
- •3.7.2. Модифікатори типу доступу в пам'яті
- •Int huge*near X;
- •3.7.3. Модифікатори const, volatile, cdecl, pascal, interrupt
- •Volatile int t;
- •Void interrupt timer()
- •Void wait(int interval)
- •Завдання для самостійної роботи
- •Принципи типізації даних
- •4.1. Прості типи даних
- •4.2. Похідні типи
- •4.3. Еквівалентність типів
- •4.4. Успадкування атрибутів
- •4.5. Перераховні типи
- •4.6. Логічні типи
- •4.7. Символьні типи
- •4.8. Числові типи
- •4.9. Структурні типи даних
- •4.9.1. Масиви
- •4.9.2. Структури
- •Int year;
- •4.10. Деякі особливості типів даних c
- •4.10.1. Базові типи даних
- •4.10.2. Перетворення типів
- •Int atoi(char s[]) /*char* s*/
- •4.10.3. Засіб typedef
- •Int curs;
- •4.10.4. Покажчики та масиви
- •Void * p;
- •Int array[12];
- •Void f(int a[])
- •Int f(char * s)
- •Наведемо деякі приклади розв'язання задач.
- •Int shift; /*відступ*/
- •Int count[n]; /*кількість монет даного типу (коефіцієнти ai)*/
- •Int coin;
- •Int sum; /*монета, яку міняємо*/
- •Int maxcoin; /*індекс по масиву cost[] монети максимальної вартості, допустимої при даному розміні.*/
- •If(count[I])
- •If(maxcoin)
- •Int* ctranspon (int *a,int n,int m)
- •Void dobutok(int* a, int* b, int** c, int n, int m)
- •Int n,m,I,size;
- •Int main()
- •4.10.5. Структури та об'єднання
- •Розглянемо деякі приклади розв'язання задач.
- •Int hashfunc(key); int eqkey(key, key);
- •Void freeval(val); void setval(val, val);
- •Void freekey(key); void setkey(key, key);
- •Int hashfunc(key key){
- •Val val; /*значення*/
- •Void set(key key, val val){
- •Void printcell(struct cell *ptr){
- •Void main(void)
- •Завдання для самостійної роботи
- •Зображення чисел у комп'ютері
- •Int main(void)
- •5.1. Системи числення
- •5.2. Правила переведення чисел з однієї системи числення в іншу
- •5.3. Правило визначення точності зображення
- •5.4. Двійкова арифметика
- •5.4.1. Додавання двійкових чисел
- •5.4.2. Зображення від'ємних чисел
- •XXXXXXXX 00000001 00000000.
- •5.4.3. Віднімання двійкових чисел
- •5.4.4. Множення двійкових чисел
- •5.4.5. Ділення двійкових чисел
- •5.5. Ознака переповнення розрядної сітки при арифметичних операціях
- •5.6. Зображення цілих чисел
- •5.7. Зображення дійсних чисел
- •5.8. Керування машинним зображенням чисел та особливості виконання арифметичних операцій
- •Завдання для самостійної роботи
- •Реалізація концепції структурного програмування
- •6.1. Оголошення та визначення функцій
- •Int d;} people;
- •6.2. Формальні та фактичні параметри
- •Void swap(int a,int b)
- •Void swap(int a,int*b)
- •6.3. Функції зі змінною кількістю параметрів
- •Void sum(char *msg,...)
- •6.5. Параметри функції main
- •6.6. Лiтернi покажчики та функцiї
- •Void strcpy(char*s,char*t)
- •Void f(void)
- •6.8. Класи пам'яті
- •Розглянемо деякі приклади розв'язання задач.
- •I, power(2,I),power(-3,I));
- •Void main() { choturukyt b; tochka *a; float s; long n,in; srand(time(null));
- •6.9. Введення–виведення с. Файли та потоки
- •6.9.1. Функції введення–виведення верхнього рівня
- •6.9.2. Функції введення–виведення консольного термінала та порту
- •Int main(void)
- •6.9.3. Функції введення–виведення нижнього рівня
- •Int main(void)
- •Int handle;
- •Розглянемо приклади розв'язання задач.
- •Void main(void)
- •Void main(argc,argv)
- •If(c& masks[I])
- •If (цей рядок довший за найдовший з попередніх)
- •Int max; /*максимальна довжина*/
- •Int len; /*довжиною цього рядка*/
- •Int nwords; /*кількість слів у рядку*/
- •If(!*s) /*рядок закінчився*/
- •Int ctr; /*кількість входжень слова*/
- •If(!strcmp(word,w[I].Wrd)){
- •If(alert){
- •Void main() { float X,y,z,t,s; int I,j,flag,n,k; m1: clrscr();
- •InitBase (void){
- •Int key, /*новий ключ*/
- •InitBase();
- •Завдання для самостійної роботи
- •7.1. Елементи концепції обєктно-орієнтованого програмування
- •Int year;
- •Int year;
- •7.3. Опис протоколу класу
- •7.4.1. Коментарі
- •7.4.2. Прототипи функцій
- •Void f();
- •7.4.5. Перевантаження функцій
- •Int Name (int first)
- •Int Name (unsigned first)
- •Int Name (int first,char*second)
- •7.4.6. Значення формальних параметрів за умовчанням
- •7.4.7. Посилання й покажчики
- •Void increment(int& X)
- •Int anotherint;
- •7.4.10. Покажчик на void
- •Void*void_ptr;
- •Void swap(void*&item1,void*&item2)
- •7.4.11. Зв'язування зі збереженням типів
- •7.4.12. Про структури та об'єднання
- •7.5. Функції-члени класу
- •X *this;
- •Int year;
- •7.6. Конструктори та деструктори
- •7.6.1. Поняття про конструктори
- •Int*data;
- •Int size;
- •7.6.3. Конструктор копіювання
- •Int data[large];
- •Inline Large1 Large1::fast(const Large1 & b)
- •7.7. Глобальні та локальні об'єкти
- •Void main(void)
- •7.8. Статична пам'ять і класи
- •Int statpol::I;
- •Vоid draw()
- •Int large;
- •Int bigwant;
- •Void f() {
- •Void g(int a)
- •7.9. Успадкування
- •7.9.1. Синтаксична реалізація успадкування
- •7.9.2. Правила доступу до полів даних
- •Void f(void)
- •Void g(void){}//...}
- •7.9.3. Конструктори та деструктори в похідних класах
- •7.9.4. Використання заміщуючих функцій-членів
- •Void Display (void); //замiщувальна функцiя
- •Void Region::Display(void)
- •Void Display(void);};
- •Void Population::Display(void)
- •7.9.5. Похідні класи й покажчики
- •7.9.6. Ієрархія типів
- •XyValue(int_x,int_y):X(_x),y(_y)
- •XyData(int_x,int_y)
- •7.9.7. Множинне успадкування
- •Void SetLoc(int_x,int_y);};
- •Int data;
- •7.10. Віртуальні функції та класи
- •7.10.1. Віртуальні функції
- •Int value;
- •Virtual int GetValue();
- •Int Value::GetValue(){return value;}
- •7.10.2. Чисті віртуальні функції. Абстрактні класи
- •Virtual void f1(void);
- •Virtual void f2(void);//...}
- •Int index;
- •7.10.3. Віртуальні деструктори
- •7.10.4. Посилання як засіб для реалізації поліморфізму
- •7.10.5. Дещо про механізм віртуальних функцій
- •Virtual int method1(float r);
- •Int data;
- •Void func(void){//тіло}};
- •Virtual public CocaCola {
- •Int size;
- •Void ShowValue(void)
- •Void ShowValues(void);};
- •Void Two::ShowValues(void)
- •7.11.2. Дружні функції
- •Void Show(One &c1,Two &c2)
- •Void Show(One &c1);
- •Void Two::Show(One &c1)
- •7.12. Перевантаження операцій
- •7.12.1. Загальний підхід
- •Void main()
- •7.12.2. Перетворення типів
- •X::operator т();
- •7.12.3. Перевантаження операції індексування масиву
- •Int znach;
- •7.12.4. Перевантаження операції виклику функції
- •Int operator()(void);
- •Int FuncClass::operator()(void)
- •Vidnosh*vec;
- •7.12.5. Перевантаження операції доступу до члена класу
- •7.12.6. Перевантаження операцій інкремента й декремента
- •Int index;
- •Void*operator new(size_t)
- •Void*operator new(size_t);
- •8.1. Функціональні шаблони
- •8.1.1. Визначення й використання шаблонів функцій
- •Void func(t t)
- •Int main(void)
- •8.1.2. Перевантаження шаблонів функції
- •Int main(void)
- •8.1.3. Cпецiалiзованi функцiї шаблона
- •Int main(void){
- •8.2. Шаблони класів
- •8.2.1. Визначення шаблонів класу
- •Void push(t t);
- •Int numitems;
- •8.2.2. Константи й типи як параметри шаблона
- •8.2.3. Використання шаблонних класів
- •Int main(void)
- •8.2.4. Спеціалізація шаблонів класу
- •Void add(t item);
- •Int main(void)
- •IArray.Add(i1);
- •Int main(void)
- •IList.Add(i1);
- •Завдання для самостійної роботи
- •Автоматна технологія програмування
- •If(!stop)printf("не входити");
- •Завдання для самостійної роботи
- •Список літератури
- •Передмова 3
Київський національний університет імені Тараса Шевченка
О.С. БИЧКОВ
Основи
сучасного
програмування
Підручник
УДК 004.432.2(075.8)
ББК 018.1я73
Б39
Рецензенти:
д-р техн. наук, проф. А.П. Власюк,
д-р техн. наук, проф. А.О. Сяський
Затверджено Вченою радою Київського національного університету імені Тараса Шевченка 5 березня 2007 року
Б39 |
Бичков, О.С. Основи сучасного програмування : підручник / О.С. Бичков. – К.: Видавничо-поліграфічний центр "Київський університет", 2008. – 272 с. |
ISBN 978-966-439-189-1
Розглянуто основи технології програмування, принципи типізації даних, зображення чисел у комп’ютері. Описано технологію програмування мовами Сі, Сі++, автоматну технологію. Класичний стиль викладу навчального матеріалу, що ґрунтується на численних прикладах, дозволяє розібратися самостійно в усіх конструкціях Сі++ та оволодіти певними прийомами й навичками програмування без залучення додаткової інформації.
Для студентів вищих навчальних закладів, що спеціалізуються в галузі інформатики.
УДК 004.432.2(075.8)
ББК 018.1я73
Гриф надано Міністерством освіти і науки України (лист № 1.4/18-г-1523 від 20.09.07)
Навчальне видання
Олексій Сергійович БИЧКОВ
ОСНОВИ СУЧАСНОГО ПРОГРАМУВАННЯ
Підручник
Редактор Н. Земляна
Оригінал-макет виготовлено Видавничо-поліграфічним центром "Київський університет"
Підписано до друку 26.12.08. Формат 70х1001/16. Вид. № 256. Гарнітура Bookman Old Style.
Папір офсетний. Друк офсетний. Наклад 200. Ум. друк. арк. 21,93. Обл.-вид. арк. 19,43. Зам. № 28-4632.
Видавничо-поліграфічний центр "Київський університет"
01030, Київ, б-р Т. Шевченка, 14, кімн. 43 (38044) 239 3222; (38044) 239 3172; факс (38044) 234 0105
e-mail: vydav_polygraph@.univ.kiev.ua
WWW: http:// vpc.univ.kiev.ua
Свідоцтво внесено до Державного реєстру ДК № 1103 від 31.10.02
ISBN 978-966-439-189-1 © Бичков О.С., 2008
© Київський національний університет імені Тараса Шевченка, ВПЦ "Київський університет", 2008
Передмова
Основи сучасного програмування Основи сучасного програмування Основи сучасного програмування Основи сучасного програмування Основи сучасного програмування Основи сучасного
У наш час існує велика кількість програмного забезпечення для автоматизації праці науковців. Це такі програмні продукти, як Maple, Mathematica, MathCad. Однак часто виникає необхідність самостійного написання бібліотек програмного забезпечення для заданої замовником предметної галузі. Для цього потрібні прикладні програмісти високого рівня кваліфікації.
У пропонованому підручнику викладено основи проектування програмного забезпечення. Матеріал базується на мовах Сі та Сі++.
Деякі розділи мають універсальний характер, їхнє засвоєння дозволить читачу надалі ефективно використовувати інші мови програмування. Це розділи, присвячені складності алгоритмів, типізації даних, поданню даних у комп'ютері (цікавий факт невиконання асоціативного закону арифметики), машинному нулю, машинній точності обчислень, програмістським умовам зупинки обчислення нескінченних сум і добутків, оптимальній реалізації обчислень, автоматній технології програмування. Наведено також алгоритми обробки інформації на різних структурах даних: простих, структурованих, усіляких видах зв'язних списків.
До книги додається електронний варіант довідника функцій мови С.
Підручник дозволить навчитися програмувати всім бажаючим, але особливо корисний він буде для студентів спеціальностей "Прикладна математика" та "Комп'ютерні науки".
Автор висловлює щиру подяку Турбалу Юрію Васильовичу за допомогу в підготовці підручника, а також рецензентам за корисні поради.
ВСТУП
Основи сучасного програмування Основи сучасного програмування Основи сучасного програмування Основи сучасного програмування Основи сучасного програмування Основи сучасного
Н. Вірт визначає поняття програмування як "алгоритми дані програми". Іншими словами можна сказати, що програма – це інструмент для виконання деяких дій над деякими даними. Що таке програмування? Це наука чи мистецтво? Давно була запропонована правильна відповідь – "технологія". А головна ідея будь-якої технології – створення таких умов, коли реалізація процесу мінімально залежить від суб'єктивних факторів. Зокрема, це означає, що сучасні засоби програмування мають забезпечувати максимальний захист від можливих помилок розробника.
Відповідно до семантики слова "технологія" під технологією програмування розумітимемо сукупність виробничих процесів, що приводять до створення необхідного програмного продукту, та їхній опис. Отже, технологія програмування – це сукупність методів і засобів розробки (написання) програм і порядок їх застосування.
Прийнято вважати, що основними типами людської інтелектуальної діяльності, що вивчається в інформатиці, є:
математичне моделювання (фіксація результатів пізнавального процесу у вигляді математичної моделі);
алгоритмізація (реалізація причинно-наслідкових зв'язків та інших закономірностей у вигляді направленого процесу обробки інформації за формальними правилами);
програмування (реалізація алгоритму на ЕОМ);
виконання обчислювального експерименту (здобуття нового знання про явище, що вивчається, або об'єкт за допомогою обчислення на ЕОМ);
розв'язання конкретних задач, що належать до об'єктів та явищ, описуваних початковою моделлю.
Обізнаність з основ програмування не зробить людину програмістом. Програмним проектам властива складність, що є зовсім не випадковою властивістю, а необхідністю. Увесь розвиток технології програмування можна розглядати як подолання хаосу при дослідженні складних систем.
Програмування як технологія у своєму розвитку пройшло кілька етапів. Програмування в машинних кодах із прямим доступом до пам'яті застосовувалося, в основному, у математичних формулах, розв'язанні задач чисельного аналізу. Використовувалась інтуїтивна технологія програмування: майже відразу приступали до складання програми за технічним завданням. Написанню послідовності машинних команд передувало складання операторної схеми, що відображала послідовність операторів і переходи між ними. Це привело до появи так званого операторного програмування. Програма "збиралася" із дрібних деталей, окремих операцій і мала достатньо просту структуру: область глобальних даних і підпрограми.
Зі збільшенням обсягів програм стали виділяти їхні окремі частини й оформляти як підпрограми. Певну кількість таких підпрограм об'єднували у бібліотеки й потім викликали із робочих програм. Це поклало початок процедурному програмуванню – велика програма подавалася сукупністю підпрограм. Одна з підпрограм була головною, з неї починалося виконання програми. Процедурний підхід вимагав структуризації майбутньої програми, розділення її на окремі процедури. При розробці окремої процедури про інші процедури треба було знати лише їх призначення і спосіб виклику.
Із поступовим розширенням сфери застосування комп'ютерної техніки ускладнюється процес програмування. Ставиться й успішно розв'язується задача створення мов, які спрощують етап власне кодування алгоритмів. Зростання складності програм приводить до появи технології структурного програмування. Здійснюються спроби формалізувати програмування як наукову дисципліну. З'являються роботи видатних учених Е. Дейкстри, Ч. Хоара, Е. Йодана, у яких розробляються формальні аспекти науки програмування. Е. Дейкстра підкреслював, що саме структуризація стане основою радикального підвищення ефективності програм за рахунок можливості автоматичного виділення однакових фрагментів, розпаралелювання процесів, конвеєрної обробки тощо.
У свою чергу, Е. Йодан розглядав структурне програмування, перш за все, з погляду всього процесу розробки, починаючи від проектування й завершуючи тестуванням і документуванням. Зазначимо, що структурні методи написання програм становлять фундамент технології низхідного, поетапного програмування, тобто безпосередньо пов'язані з питаннями керування проектом у цілому.
Паралельно приходить розуміння, що кількість задач, для яких принципово можна розробити формально бездоганні специфікації, з розширенням сфери застосування прикладного програмного забезпечення зменшується. Даний підхід можна охарактеризувати як деревоподібну технологію структурного програмування.
Розглянемо один із напрямів деревоподібного підходу, який називається низхідним програмуванням. Його суть полягає в розбитті великої задачі на менші, незалежні підзадачі, які можуть розглядатися окремо. Таким чином, ми переходимо від загального розгляду проблеми, що розв'язується, до розгляду специфічних підзадач.
Спочатку будується структура задачі у вигляді дерева. Далі почергово програмуються підзадачі, починаючи із самого верхнього рівня. Після того, як усі підзадачі запрограмовані, проводиться їх почергове тестування й налагодження в такому самому порядку. При цьому вся необхідна вхідна інформація формується своєчасно. Кожна підзадача, у даному випадку – підпрограма, тестується при нормальних вихідних даних, які виробляються іншими підпрограмами.
Зауважимо, що багато великих систем не мають верхнього рівня. Наприклад, у системі керування базою даних важко, а інколи й неможливо, виділити функцію, яка є її найважливішою ланкою.
Низхідне програмування не перешкоджає створенню загальних підпрограм, які використовуються багатьма іншими програмами, але й не стимулює цей процес. Ідея об'єднання повторно використовуваних підпрограм у систему виявляється у висхідному підході, що є альтернативою низхідному.
Суть висхідного програмування: спочатку будується структура задачі у вигляді дерева; потім по черзі програмуються підзадачі, починаючи з найнижчого рівня, у такому порядку, щоб для кожної підзадачі, яка програмується, були вже запрограмовані всі підзадачі, до яких вона може звертатися.
За висхідного тестуванняі для кожної підпрограми (крім головної) доводиться створювати провідну програму, яка має підготувати для тестованої підпрограми необхідний стан інформаційного середовища та провести звернення до неї. Це приводить до великого обсягу налагоджувального – додаткового – програмування.
Основні правила успішного застосування цієї технології:
формалізований і строгий опис програмістом входів функцій і виходів усіх модулів програми й системи;
узгоджена розробка структур даних і алгоритмів;
обмеження обсягу підпрограм.
Даною технологією зумовлюється певний принцип декомпозиції та ієрархічна структура програми.
Низхідне й висхідне програмування можна узагальнити як структурне. Основоположником структурного програмування вважається Е. Дейкстра. Його революційна для свого часу робота вийшла друком 1965 року та здійснила переворот у думках багатьох.
Низхідне програмування найкраще застосовується до проблем, що мають чітко виражений ієрархічний характер. На жаль, більшість реальних проблем його не мають. Зауважимо, що фокусування на функціональності (розбиття на підзадачі й методи їх розв'язання) допускає абстрагування від даних.
Теоретичними основами структурного програмування є:
формальні системи теорії обчислюваності, загальні рекурсивні функції, системи Поста, алгоритми Маркова, лямбда-числення Черча;
аналіз програм за низхідною схемою, декомпозиція, заснована на розбитті задач за рівнями 0, 1,..., к.
У класичній роботі С. Бома й Г. Джакопіні показано, що ієрархічна структура, розбита на рівні, може бути реалізована в мові, що включає лише три керувальні конструкції. За Бомом і Джакопіні, для реалізації програм потрібні такі основні складові:
функціональний блок (конструкція проходження);
конструкція узагальненого циклу;
конструкція двійкового, або дихотомічного, розв'язання.
Характерними рисами структурного програмування є:
простота та ясність (коментування);
використання лише базових конструкцій;
відсутність багатоцільових функціональних блоків;
відсутність невиправдано складних арифметичних і логічних конструкцій;
розташування в рядку програми не більше одного оператора мови програмування;
змістовність імен змінних.
Структурний підхід аналізує й оперує, перш за все, діями, які необхідно виконувати з даними. Проте кожна реальна задача із часом доповнюється новими даними, проблемами, модифікується. Низхідний підхід створює хорошу програмну модель лише для початкових вимог до розв'язання задачі. Тому подібна архітектура поступово втрачає пристосовність до розв'язання задач.
Подальший розвиток структурного програмування спричинив появу його різновиду – модульного програмування. Незалежні фрагменти задачі оформляються як модулі.
Програмний модуль – це будь-який фрагмент опису процесу, що оформляється як самостійний програмний продукт, придатний для використання. Це означає, що кожен програмний модуль програмується, компілюється та налагоджується окремо від інших модулів програми й тим самим фізично відділяється від них.
Створюються бібліотеки модулів, розробляється механізм їхнього включення до програми. Модуль повинен мати строго визначений інтерфейс і приховану частину, одну точку входу й одну – виходу. Зароджуються та здійснюються ідеї розділення специфікації й реалізації модулів, використання модулів, що приховують структури даних.
Модульна програма має деревоподібну структуру. У вузлах такого дерева розміщуються програмні модулі, а напрямлені дуги показують їх підлеглість. Модульна структура програми включає сукупність специфікацій модулів, що її створюють. Специфікація програмного модуля містить синтаксичну специфікацію його входів, що дозволяє побудувати використовуваною мовою програмування синтаксично правильне звернення до нього й функціональну специфікацію модуля – опис семантики функцій, що виконуються ним за вхідними даними.
Основою структурного та модульного програмування є декомпозиція. Однак, оскільки вона лише торкається функціональних аспектів, то і вплив структури даних на розв'язання втрачається.
Програмування, пройшовши наївну й формальну фазу розвитку (якщо трохи переформулювати Д. Гільберта), вступає у фазу практичну. Наведемо цитату з книги Г. Майєрса [11]: "Низхідне функціональне проектування погано адаптується до розробки великих програмних систем. Низхідне проектування залишається корисною парадигмою для малих програм та індивідуальних алгоритмів.., але воно практично не масштабується на великі системи. Сенс не в тому, що Ви не можете розробляти систему зверху вниз: можете. Але, виторговуючи для себе короткочасну зручність за тривалу негнучкість, Ви некоректно нагромаджуєте одну функцію над іншою і (досить часто) функціональний інтерфейс над важливішими параметрами системи. Ви випускаєте з уваги аспект даних, і Ви жертвуєте можливістю багатократного використання".
Сучасний розвиток теорії програмування полягає у створенні програмних проектів, що базуються на об'єктно-орієнтованому підході. Це привело до створення візуальних середовищ швидкої розробки проектів, заснованих на компонентній ієрархії.
Розвиток підходу, заснованого на компонентній ієрархії, ще не завершився. Зараз він перебуває на стадії, коли розробку проекту можна починати не зі складання формальних специфікацій, а зі створення макета програми, тобто користувач і програміст можуть виробити єдине розуміння того, що має робити програма.
Розглянуті вище технології програмування фокусують увагу окремо на операціях і даних. Основна відмінність між структурним, модульним і сучасним підходами до проектування програмного забезпечення полягає в тому, що вони відповідають на різні питання: "Що робить програма" і "Що робиться з...". Це привело до формування технології, відомої як об'єктно-орієнтоване програмування.
Сучасне об'єктно-орієнтоване програмування можна вважати (і це буде показано далі) черговим якісним витком розвитку структурного й модульного програмування. Воно характеризується трьома основоположними ідеями: інкапсуляцією, успадковуванням, поліморфізмом.
Інкапсуляція. Поєднання даних з допустимими операціями над ними привело до нового типу даних – об'єкта. З об'єктом можна працювати лише так, як указано в інструкціях, і здійснювати лише операції, закладені в його описі. Насправді об'єкт є змінною визначеного користувачем типу. Здається дивним, що об'єкт, який об'єднує коди й дані, можна розглядати як змінну. Проте для об'єктно-орієнтованого програмування це саме так. Опосередковане звернення до даних дозволяє уникнути в багатьох випадках непередбачених, небажаних змін параметрів.
Успадковування. Дана властивість полягає в успадковуванні характеристик одного об'єкта іншим. Для цього один з об'єктів оголошується нащадком іншого, який, у свою чергу, стає предком цього нового об'єкта. Нащадок успадковує всі параметри свого предка та його операції (методи), тому повторно описувати їх немає необхідності, а використовувати можна. Це істотно спрощує запис схожих об'єктів, якщо встановити між ними спадковий зв'язок.
Поліморфізм. Це властивість, яка дозволяє одне й те саме ім'я використовувати для розв'язання двох і більше схожих, але різних задач. Він дає змогу в об'єктно-орієнтованому програмуванні використовувати одне ім'я для задання загальних для класу дій. Виконання кожної конкретної дії визначається типом даних. У загальнішому значенні концепцією поліморфізму є ідея "один інтерфейс – множина методів". Це означає, що можна створити загальний інтерфейс для групи близьких за значенням дій. Перевага поліморфізму полягає в тому, що він допомагає спрощувати програми. Вибір же конкретної дії, залежно від ситуації, покладається на компілятор. Ключовим у розумінні поліморфізму є те, що він дозволяє маніпулювати об'єктами різної міри складності шляхом створення загального для них стандартного інтерфейсу для реалізації схожих дій.
Об'єктно-орієнтоване проектування – це методологія проектування, що сполучає в собі процес об'єктної декомпозиції і прийоми зображення логічної й фізичної, а також статичної й динамічної моделей проектованої системи.
Розглянемо основні ідеї об'єктно-орієнтованого підходу:
програма є моделлю деякого реального процесу;
об'єкт описується набором параметрів, значення яких визначають стан об'єкта, і набором операцій (методів), які може виконувати об'єкт;
об'єкти, описані одним і тим самим набором параметрів і здатні виконувати один і той самий набір дій, належать до класу однотипних.
З погляду мови програмування, клас об'єктів можна розглядати як тип даного, а окремий об'єкт – як дане цього типу. Визначення програмістом власних класів об'єктів для конкретного набору задач дозволяє описувати окремі задачі в термінах самого класу задач. Таким чином, об'єктно-орієнтований підхід припускає, що при розробці програми мають бути визначені класи використовуваних у програмі об'єктів і побудовані їх описи, потім створені необхідні об'єкти й визначена взаємодія між ними.
Однак на об'єктно-орієнтованому програмуванні розробка нових технологій не завершилася. Зараз на його базі розвивається нова технологія – COM.
COM (Component Object Model) розшифровується як "компонентна об'єктна модель". Суть цієї технології полягає в тому, що програми будуються із компонент, які складаються з об'єктів. Таким чином, можна сказати, що ця технологія "виросла" з модульного та об'єктно-орієнтованого підходу до побудови програм. Новизною можна вважати те, що компонентами й об'єктами є не початкові тексти, що не включаються та компілюються сумісно з проектом, не бібліотеки стандартних програм, що приєднуються лінкером, а безпосередньо виконувані бінарні файли. Їх не треба зв'язувати з проектом – достатньо зареєструвати в операційній системі, щоб зробити доступними для будь-якої програми. Вони застосовуються у програмі без використання операцій складання модуля.
Технологія COM розповсюджує переваги об'єктно-орієнтованого програмування, доступні програмісту на рівні початкового тексту, на двійковий рівень.
Слід також приділити увагу технології, що набирає обертів –.NET, хоча її не можна розглядати як чисто програмістську. Вона скоріше є своєрідною платформою для розв'язання сучасних задач. Використання суфікса .NET може не лише вказувати на наявність у продукті конкретних нових технологій, але й відображати напрям його розвитку. Однак у цьому підручнику ми не розглядатимемо детально дві останні технології.
1