Теоретичні відомості
Типи об'єктів і, зокрема, компоненти бібліотек C++Builder оформляються у вигляді класів. Класи — це типи, визначені користувачем. У класах описуються властивості об'єкту, його методи і події, на які він може реагувати. Мова програмування C++ передбачає тільки інструментарій створення класів. А самі класи створюються розробниками програмного забезпечення. Творці C++Builder розробили безліч корисних класів і включили їх в бібліотеки системи. Цими класами ви користуєтесь при роботі в Інтегрованому Середовищі Проектування. Якби при створенні нового класу вам довелося все починати з нуля, то ефективність цього заняття була б під великим сумнівом. Дійсно, уявіть собі, що при розробці нового компоненту, наприклад якої-небудь нової кнопки, вам довелася б створювати все: малювати її зображення, описувати всі властивості, що визначають її місце розташування, розміри, надписи і малюнки на її поверхні, колір, шрифти, описувати методи, реалізуючи її поведінку — зміну розмірів, видимість, реакцію на повідомлення, які поступають від клавіатури і миші. Насправді все набагато простіше, завдяки одній важливій властивості класів - спадкоємству. Новий клас може успадковувати властивості, методи, події свого батьківського класу, тобто того класу, на основі якого він створюється. Наприклад, при створенні нової кнопки можна узяти за основу один з вже розроблених класів кнопок і лише додати до нього нові властивості або відмінити якісь властивості і методи батьківського класу. Оголошення класів Поняття класу, структури та об’єднання в С++ досить близькі один до одного. Тому все, що стосується класів можна застосовувати до структур та об’єднань.
Клас повинен бути оголошений до того, як буде оголошена хоч одна змінна цього класу. Тобто клас не може оголошуватись всередині оголошення змінної. Синтаксис оголошення класу наступний: class < ім’я класу >: < список класів батьків > { public: //доступно всім < дані, методи, властивості, події > _published //доступні в Інспекторі Об’єкта і змінювані < дані, властивості > protected: //доступно лише нащадкам < дані, методи, властивості, події > private: // доступно лише в класі < дані, методи, властивості, події > } < перелік змінних >; Наприклад: Class MyClass: public Class1, Class2 { public: MyClass (int=0); void SetA (int); int GetA(void); private: int FA; double B, C; protected: int F (int); }; Оголошення класів слід розміщувати в заголовному файлі модуля, а реалізацію функцій — елементів в окремому файлі реалізації. При цьому в оголошенні класу повинні міститися тільки прототипи функцій. Це витікає з принципу приховування інформації — одного з основних в об'єктно-орієнтованому програмуванні. Така організація програми забезпечує незалежність всіх модулів, що використовують заголовний файл з оголошенням класу, від якихось змін в реалізації функцій-елементів класу. Ім’я класу може бути будь-яким допустимим ідентифікатором. Ідентифікатори класів, що наслідують класи бібліотеки компонентів С++ Builder, прийнято починати з символу «Т». Клас може наслідувати поля (дані-елементи), методи (функції-елементи), властивості, події від інших класів або вводити нові. Якщо передбачається такі батьківські класи, то в оголошенні класу після його імені ставляться дві крапки, а потім зазначається список батьків. Якщо клас, що оголошується не має попередників, то список класів-батьків опускається. Наприклад: Class MyClass1 { … }; Доступ до оголошуваних елементів класу визначається тим, в якому розділі вони оголошені. Розділ public (відкритий) призначений для оголошень, які доступні для зовнішнього використання. Це відкритий інтерфейс класу. Розділ published (публікований) містить відкриті властивості, які з'являються в процесі проектування на сторінці властивостей Інспектора Об'єктів і які, користувач може встановлювати в процесі проектування.
Розділ private (закритий) містить оголошення полів і функцій, використовуваних тільки усередині даного класу. Розділ protected (захищений) містить оголошення, доступні тільки для нащадків оголошуваного класу. Проте на відміну від закритих елементів, захищені елементи залишаються доступними для програмістів, яким необхідно створити від цього класу похідні класи, причому не потрібно, щоб похідні класи оголошувалися в цьому ж модулі. В наведеному вище прикладі через об’єкт даного класу можна отримати доступ лише до функцій MyClass, SetA, GetA. Поля FA, В, С і функція F – закриті елементи. Це допоміжні дані і функція, які використовують у своїй роботі відкриті функції. Відкрита функція MyClass з іменем, що співпадає з іменем класу, це так званий конструктор класу, який повинен ініціалізувати дані в момент створення об’єкта класу. Наявність конструктора в оголошенні класу не обов’язкова. Перед іменами класів-батьків в оголошенні класу також може указуватися специфікатор доступу (у прикладі public). Сенс цього специфікатора той же, що і для елементів класу: при спадкоємстві public (відкрите спадкоємство) можна звертатися через об'єкт даного класу до методів і властивостей класів-предків, при спадкоємстві private подібне звернення неможливе. За замовчуванням в класах (на відміну від структур) передбачається специфікатор private. Тому можна включати в оголошення класу дані і функції, не вказуючи специфікатора доступу (public). Все, що включено в опис до першого специфікатора доступу, вважається захищеним. Аналогічно, якщо не вказаний специфікатор перед списком класів-батьків, передбачається захищене наслідування. Оголошення даних-елементів (полів) виглядає так же, як оголошення змінних чи оголошення полів в структурах: < тип > < імена полів >; В оголошеннях класу поля забороняється ініціалізувати. Для ініціалізації даних служать конструктори. Оголошення функцій-елементів в найпростішому випадку не відрізняються від звичайних оголошень функцій.
Динамічне створення екземпляра класу - об'єкту Після того, як оголошений клас, можна створювати об’єкти цього класу. Якщо клас не наслідує класам бібліотек компонентів С++ Builder, то об’єкт класу створюється як будь-яка змінна іншого типу простим оголошенням. Наприклад, оператор MyClass МС, МС10 [10], *Pmc; створює об’єкт МС оголошеного вище класу MyClass, масив МС10 з десяти об’єктів даного класу і покажчик Pmc на об’єкт цього класу. У момент створення об'єкту класу, що має конструктор, можна ініціалізувати його дані, перераховуючи в дужках після імені об'єкту значення даних. Наприклад, оператор MyClass MC(3); не тільки створює об'єкт МС, але і задає його полю FA значення 3. Якщо цього не зробити, то у момент створення об'єкту поле отримає значення за умовчанням, вказане в прототипі конструктора, що міститься в оголошенні класу. Створення змінних, що використовують клас, можна сумістити з оголошенням самого класу, розміщуючи їх список між фігурною дужкою, що закриває клас, і завершується крапкою з комою. Наприклад: class MyClass: public Classl, Class2 { } МС, МС10[10], *Pmc; В процесі роботи об'єкти можуть створюватися і знищуватися. Таким чином, структура програми є динамічним утворенням, змінним в процесі виконання. Основна мета створення і знищення об'єктів — економія ресурсів комп'ютера і, перш за все, пам'яті. З метою організації динамічного розподілу пам'яті для всіх об'єктів існують методи їх створення — конструктори і знищення — деструктори. Конструктори об'єктів, які спочатку повинні бути присутніми в додатку (прикладній програмі), спрацьовують при запуску програми. Деструктори всіх об'єктів, наявних в даний момент в додатку, спрацьовують при завершенні його роботи. Але нерідко і в процесі виконання різні нові об’єкти (наприклад, нові вікна документів) динамічно створюються і знищуються за допомогою їх конструкторів і деструкторів. Якщо створюється динамічно розміщуваний об'єкт класу, то це робиться операцією new. Наприклад: MyClass *PMC = new MyClass; або MyClass *РМС1 = new MyClass(3);
Ці оператори створюють в динамічно розподіленій області пам'яті самі об'єкти і створюють покажчики на них — змінні РМС і РМС1. Створення об'єктів класу простим оголошенням змінних можливо тільки у випадку, якщо серед предків вашого класу немає класів бібліотеки компонентів C++Builder. Якщо ж такі предки є, то створення покажчика на об'єкт цього класу можливо тільки операцією new. Наприклад, якщо клас оголошений так: class MyClass2: public TObject { ... }; то створення покажчика на об'єкт цього класу може здійснюватися оператором MyClass2 *Р2 = new MyClass2; Організація спадкоємства, множинне спадкоємство Спадкоємство (inheritance) - здатність одного класу успадковувати можливості або властивості іншого класу. В C+ + один клас може наслідувати інший наступним чином: class Student { }; class GraduateStudent: public Student { }; В даному прикладі GraduateStudent успадковує всі члени класу Student. Таким чином, GraduateStudent являється студентом. Звичайно, при цьому GraduateStudent може також містити унікальні, властиві саме йому члени. Спадкоємство було включене в C++ з кількох причин. Звичайно, основною з них була необхідність виражати зв'язки між класами за допомогою спадкоємства. Менш важливою метою було зменшення розміру програмного коду. Спадкоємство дозволяє пристосовувати існуючі класи до нових додатків, не вносячи змін до їх змісту. Існуючий клас наслідується новим підкласом, який і міститиме всі необхідні додатки і зміни. Уявіть собі, що ви успадковуєте якийсь існуючий клас. Потім ви знаходите, що базовий клас містить помилку, яку потрібно виправити. Якби ви переробляли клас для його повторного використання, вам би довелося уручну перевірити новий клас, відшукуючи помилку в кожному окремо взятому додатку. Проте якщо ви наслідували клас без змін, то можете без особливого клопоту замінити стару версію класу новою. При опису нового класу, похідного від якогось одного чи декількох базових класів, можна додавати нові функції-елементи і дані-елементи, зберігаючи при цьому всі елементи батьків, а можна батьківські елементи перевизначити або перезавантажити. В похідному класі доступні відкриті і захищені елементи базового класу. Закриті елементи базового класу в похідному класі недоступні. Похідний клас може унаслідуватися від базового класу як public, protected або private. Захищене і закрите наслідування зустрічаються рідко і кожне з них потрібно використовувати з великою обережністю. Одиночне спадкоємство підходить для опису більшості об'єктів реального світу. Проте деякі класи представляють собою поєднання декількох класів в одному. Клас може бути спадкоємцем більш ніж одного базового класу. Таке спадкоємство називається множинним.
Доступ до членів об'єкту (даним і функціям) Функції-елементи класу мають доступ до будь-яких інших функцій-елементів і до будь-яких даних-елементів, як відкритих, так і закритих. Клієнти класу (якісь зовнішні функції, що працюють з об'єктами даного класу) мають доступ тільки до відкритих функцій-елементів і даних-елементів. Але в деяких випадках бажано забезпечити доступ до закритих елементів для функцій, що не є елементами даного класу. Це можна зробити, оголосивши відповідну функцію як друга класу за допомогою специфікації friend. Наприклад, якщо в оголошення класу включити оператора friend void INCFA(MyClass *); то функція INCFA, не будучи елементом даного класу, дістає доступ до його закритих елементів. Наприклад, функція INCFA може бути описана десь в програмі таким чином: void INCFA(MyClass *P) (P->FA++;) Приклад Написати програму, яка б у графічному режимі відображала на робочій формі у вказаному курсором місці окружність з лінією та показувала координати положення курсору (центр окружності). Для програмної реалізації спочатку створюється проект, форма якого складається з компонентів Edit (для вказування радіусу кола), Button, Label (відображення координат) і має вигляд, зображений на рисунку 6.1. Рисунок 6.1 – Розміщення компонентів на формі У header-файлі оголошуємо батьківський клас Р1 та клас, що його наслідує РР1. class P1 { protected: int coordX,coordY; public: void ini_coord(int X, int Y) { coordX=X; coordY=Y; }; int out_X() { return coordX; }; int out_Y() { return coordY; }; }; class PP1:public P1 { int radius; public: void circum(TForm1 *Form1) { Form1->Canvas->Ellipse(coordX,coordY, coordX+radius, coordY+radius); Form1->Canvas->MoveTo(coordX,coordY); Form1->Canvas->LineTo(coordX + floor(1.1* radius),coordY+ floor(1.1* radius)); }; void ini_radius(int r) { radius=r; }; }; За допомогою покажчиків посилаємось на оголошені класи: P1 *pP1; PP1 *pPP1; При події створення форми (FormCreate) необхідно в файл Unit1.срр записати обробник, який створить екземпляри класів. void __fastcall TForm1::FormCreate(TObject *Sender) { pP1=new P1; pPP1=new PP1; } При події FormClick задається обробник, який відображатиме координати курсору. Label1->Caption=IntToStr(pP1->out_X()); Label2->Caption=IntToStr(pP1->out_Y()); Подія, що виникає при натисканні кнопки миші FormMouseUp викликає обробник визначення координат курсору pP1->ini_coord(X,Y); pPP1->ini_coord(X,Y); Для кнопки “Drow” оброблювач натискання малює коло з лінією, вказаного у вікні Edit радіусу (рисунок 6.2). pPP1->ini_radius(StrToInt(Edit1->Text)); pPP1->circum(Form1); Рисунок 6.2 – Результат роботи програми На рисунку 6.2 показані координати останнього намальованого кола (його центру) з радіусом рівним 80. Після закінчення роботи програми по закриттю форми необхідно очистити пам'ять від об’єктів. Для цього у Редакторі Коду необхідно прописати наступний код: delete pP1; delete pPP1;
Читайте также: Cтислі теоретичні відомості Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|