Дружні функції та правила їхнього використання 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Дружні функції та правила їхнього використання



Дружня функція – функція, яка описується в межах класу, але реалізація її знаходиться в іншому класі. При цьому вона має повний доступ до закритої частини класу. Дружні функції властиві далеко не для всіх мов програмування. Розглянемо приклад дружньої функції на мові С++:

 

//файл Square.h #pragmaonce #include“Point.h“ #include <iostream> using namespace std; /** @class Square Клас – абстракція квадрата */ class Square   private: /// Координати лівого верхнього кута квадрата Point *top_left; /// Довжина сторони квадрата double side_length; public: /// Конструкторзазамовчанням Square(void); /// Конструктор з параметрами /// @param _top_left – координати лівого верхнього кута квадрата /// @param _side_length – довжина сторони квадрата Square(Point *_top_left, double _side_length); /// Метод – обчислення площі квадрата /// @return - повертає значення площі, представлене дробовим числом double area_of_square(); /// Метод - обчислення периметра квадрата /// @return - повертає значення периметра, представлене дробовим числом doubleperimeter(); /// Дружня функція – виведення даних про квадрат /// @param it – посиланняобєкткласу friend void show(Square *_it); /// Деструктор ~Square(void); };

 

//Файл friend_funktion.h #include “Square.h“ #include <iostream> using namespace std; void show(Square *_it) { cout<<“Information about square:”<<endl; cout<<“A(“<<_it->top_left->get_x()<<“; “<<_it->top_left->get_y()<<“)”<<endl; cout<<“B(“<<_it->top_left->get_x() + _it->side_length<<“; “<<_it->top_left->get_y()<<“)”<<endl; cout<<“C(“<<_it->top_left->get_x() + _it->side_length< <“; “<<_it->top_left->get_y() – _it->side_length<<“)”<<endl; cout<<“D(“<<_it->top_left->get_x()<<“; “<<_it->top_left->get_y() – _it->side_length<<“)”<<endl; }

Отже опис дружньої функції починається із ключового слова friend, далі вказується тип даних який повертається, назва функції, список параметрів в дужках. Зазвичай для отримання доступу до закритих даних об’єкта в списку параметрів вказується посилання на поточний об’єкт, як у прикладі.

Одною із цілей використання дружньої функції є опис бінарних операторів для класів.

Деельлєльки та їх застосування

DLL (англ. Dynamic-link library — динамічно приєднувана бібліотека) — реалізовані компанією Microsoft загальні бібліотеки в ОС Windows та OS/2. Як правило бібліотеки мають розширення файлу *.dll, *.ocx (для бібліотек, що містять елементи керування ActiveX) або *.drv (драйвери старих версій ОС). Структура DLL така сама, як і в PE-файлів (Portable Executable) для 32-, 64-розрядних Windows, та New-Executable (NE) для 16-бітових Windows. DLL може містити код, дані та ресурси в будь-якій комбінації.
Популярний вступ
Різні програми багатовіконного середовища часто виконують однакові дії, наприклад, хрестик в правому верхньому куті вікна, який закриває його, малюється більшістю програм однаково. Марнотратно було б, щоб кожна із цих програм мала відповідну функцію — це роздувало б їхні розміри. Тому, розумно, щоб такі функції поступали в спільне користування. Для цього служать бібліотеки з динамічним зв'язуванням. Відповідні функції завантажуються в пам'ять комп'ютера не з файлу програми, а із спеціального файлу, вже при виконанні. Насправді, операційна система не завантажує їх повторно. Якщо програма при запуску вимагає завантаження динамічної бібліотеки, то операційна система перевіряє, чи така бібліотека вже є в пам'яті. Якщо вона є, то операційна система збільшує лічильник клієнтів для динамічної бібліотеки на одиницю. При завершенні роботи, програма повідомляє операційну систему про необхідність вивантажити динамічну бібліотеку. При цьому операційна система зменшує лічильник клієнтів на одиницю. Якщо після такого зменшення кількість клієнтів стає рівною нулю, то тоді динамічна бібліотека справді вивантажується із пам'яті комп'ютера.
Під Windows динамічні бібліотеки зберігаються в файлах із розширенням *.dll. Крім підпрограм там можуть також зберігатися інші ресурси, наприклад, іконки чи бітмапи. В коді програми, що використовує функції з динамічної бібліотеки, завантаження та вивантаження бібліотеки повинні бути прописані безпосередньо. Компілятору не потрібен код функцій, що містяться в динамічних бібліотеках. При запуску програми, вона, однак, шукатиме відповідну dll. Якщо така dll не знайдена на комп'ютері, то програма здебільшого виконуватися не буде, а видасть повідомлення про відсутність динамічної бібліотеки.

53ПДФ Документ …

54 Вказівник this
Ім'я this є службовим (ключовим) словом. Явно описати чи визначити вказівник this не можна. Відповідно до неявного визначення this є константним вказівником, тобто змінювати його не можна, однак у кожної приналежної класу функції він указує саме на той об'єкт, для якого функція викликається. Говорять, що вказівник this є додатковим (схованим) параметром кожної нестатичної компонентної функції. Іншими словами, при вході в тіло приналежній класу функції вказівник this ініціалізується значенням адреси того об'єкта, для якого викликана функція. Об'єкт, що адресується вказівником this, стає доступним усередині приналежної класу функції саме за допомогою вказівника this. При роботі з компонентами класу усередині приналежної класу функції можна було б скрізь використовувати цей вказівник. Наприклад, зовсім правильним буде таке визначення класу:
struct ss
{ int si;
char sc;
ss(int in, char en) // Конструктор об'єктів класу.
{ this->si = in; this->sc = en; }
void print(void) // Функція висновку відомостей про об'єкт.
{ cout «"\n si = " «this->si;
cout «"\n sc = " «this->se; }
};
При такому використанні вказівника this немає ніяких переваг, тому що дані конкретних об'єктів доступні в приналежних класу функціях і за допомогою імен даних класу. Однак у деяких випадках вказівник this корисний, а іноді просто незамінний. У наступному прикладі вказівник this дозволяє компілятору розібратися в ситуації, коли ім'я Meaning компонента класу збігається з ім'ям формального параметра приналежної класу функції:
//OOР11_1.СРР - вказівник "this".
#include
class cell// Клас "числовий елемент".
{
int static Amount; // Загальна кількість елементів.
int Number; // Порядковий номер елемента.
double Meaning; // Значення елемента.
public:
//Конструктор:
cell(double Meaning = 0.0)
{ // Змінюємо значення статичного компонента:
Amount++;
this -> Number = Amount;
// Компонент і однойменний параметр:
this -> Meaning = Meaning; }
// Висновок зведень про об'єкт і кількість елементів:
void display (void)
{
// Зайві this:
cout «"\nNumber = " «this->Number;
cout «" Amount = " «this->Amount;
cout «" Meaning = " «this->Meaning;
}
};
// Ініціалізація статичного компонента:
int cell::Amount = 0;
void main(void){ cell A;// Об'єкт зі значенням, що умовчується.
A.display();
cell B(200.0);
cell C(300.0);
B.display();
C.display();

}Результат виконання програми:
Number = 1 Amount = 1 Meaning = 0
Number = 2 Amount = 3 Meaning = 200
Number = 3 Amount = 3 Meaning = 300
Майже незамінним і дуже зручним вказівник this стає в тих випадках, коли в тілі приналежної класу функції потрібно явно задати адресу того об'єкта, для якого вона викликана. Наприклад, якщо в класі потрібна функція, що поміщає адресу обраного об'єкта чи класу в масив яка включає конкретний об'єкт класу в список, те таку функцію складно написати без застосування вказівника this. Дійсно, при організації зв'язних списків, ланками яких повинні бути об'єкти класу, необхідно включати в зв'язку ланок вказівник саме на той об'єкт, що у даний момент обробляється. Це включення повинне виконати якась функція-компонент класу. Однак конкретне ім'я об'єкта, що включається, у момент написання цієї приналежної класу функції недоступно, тому що його набагато пізніше довільно вибирає програміст, використовуючи клас як тип даних. Можна передавати такої функції посилання чи вказівник на потрібний об'єкт, але набагато простіше використовувати вказівник this.

Графічний Редактоор

1. Створимо папку MyGrRED, запустимо C++ Builder 2010 у віконному режимі і запишемо у нашу папку пустий проект.

2. Ставимо на форму 2 компоненти TImage, розташуємо їх у нижній лівій частині форми у вигляді двох квадратів розміром 20х20 пікселів. Це будуть віконця для вибору основного і допоміжного кольорів. Назвемо їх Image1 і Image2.

3. Ще один TImage розташуємо так, щоб він займав майже всю площу форми. Це буде наш мольберт. Назвемо його Image3.

4. Ставимо внизу форми ще одну компоненту TImage, на якій пізніше розмістимо палітру кольорів.

5. Тому вона повинна мати таку довжину, щоб на ній помістилося 10 квадратиків по 20х20 пікселів. Назвемо її Image4.

6. Ставимо на форму кнопку TSpeedButton, розташувавши її у верхньому лівому куті форми і назвавши її SBBrush. Щоб кнопка фіксувалась у натисутому та відпущеному станах, встановимо значення її властивості GroupIndex в 1, а AllowAllUp в true. Завантажимо у властивість Glyph піктограму пензлика (Brush.bmp).

7. Нижче кнопки SBBrush ставимо ще одну компоненту TspeedButton з назвою SBColor. Вона відповідатиме за вказівник кольору піксела при малюванні. Також встановимо значення її властивості GroupIndex в 1, а AllowAllUp в true. Тепер тільки одна із цих двох кнопок буде у натиснутоу стані. Завантажимо у її властивість Glyph піктограму one2one.bmp.

8. Поставимо на форму OpenPictureDialog.

9. Поставимо на форму компоненту MainMenu

Створимо розділ Файл з підрозділом Відкрити.

Назвемо його MOpen. Створимо розділ Правка

Створимо обробники подій.

10. У заголовний файл модуля вставимо оператор:

Graphics::TBitmap * BitMap = new Graphics::TBitmap; Цим ми створюємо об’єкт BitMap типу TBitMap, у якому буде зберігатись зображення для його відновлення, в разі потреби, командою Відміна.

11. Для події OnCreate форми створимо її обробник:

// задаємо властивості пензля для основного і допоміжно-го кольорів

Image1->Canvas->Brush->Color = clBlack;

Image2->Canvas->Brush->Color = clWhite;

// заповнимо віконця основного і допоміжного кольорів

Image1->Canvas->FillRect (Rect (0, 0, Image1 -> Width, Image1 -> Height));

Image2->Canvas->FillRect (Rect (0, 0, Image2 -> Width, Image2 -> Height));

// задаємо ширину елементів палітри кольорів

int HW = Image4->Width / 10;

//зафарбуємо елементи палітри кольорів

for (int i = 1; i <=10; i++){ switch (i)

{case 1: Image4->Canvas->Brush->Color = clBlack; break;

case 2: Image4->Canvas->Brush->Color = clAqua; break;

case 3: Image4->Canvas->Brush->Color = clBlue; break;

case 4: Image4->Canvas->Brush->Color = clFuchsia; break;

case 5: Image4->Canvas->Brush->Color = clGreen; break;

case 6: Image4->Canvas->Brush->Color = clLime; break;

case 7: Image4->Canvas->Brush->Color = clMaroon; break;

case 8: Image4->Canvas->Brush->Color = clRed; break;

case 9: Image4->Canvas->Brush->Color = clYellow; break;

case 10: Image4->Canvas->Brush->Color = clWhite; }

Image4->Canvas->Rectangle ((i -1) * HW, 0, i *HW, Image4 -> Height);}

// малюємо лінії на канві (для прикладу)

Image3 -> Canvas -> MoveTo (0, 0);

Image3 -> Canvas -> LineTo (Image3 -> Width, Image3 -> Height);

Image3 -> Canvas -> MoveTo (0, Image3 -> Height);

Image3 -> Canvas -> LineTo (Image3 -> Width, 0);

BitMap -> Assign (Image3 -> Picture); }

Тут ми задали кольори вікон: основного (Image1) – бі-лий і допоміжного (Image2) – чорний. Функцією FillRect заливаємо вікна цими кольорами. Потім формуємо палітру кольорів з допомогою ф-ції Rectangle. Потім малюємо діагональні лінії на Image3. Останній оператор запам’ятовує малюнок з Image3 в об’єкті BitMap методом Assign.

12. Активізуємо на формі Image3 і в Object Inspector, перейшовши на закладку Events, створимо обробник події ОтMouseDown і запрограмуємо його так:

if ((Sender == Image4) || SBColor->Down)// режим установки основного и допоміжного кольорів{ if (Button == mbLeft){// установка основного кольору

Image1->Canvas->Brush->Color = ((TImage *)Sender) ->Canvas->Pixels[X][Y];

Image1->Canvas->FillRect (Rect (0, 0, Image1->Width, Image1->Height)); }

else { // установка допоміжного кольору

Image2->Canvas->Brush->Color = ((TImage *)Sender)-> Canvas->Pixels[X][Y];

Image2->Canvas->FillRect(Rect(0,0,Image2->Width, Image2->Height)); } }

13. В закладці Event вікна Object Inspector за-програмуємо OnDestroy - обробник події фо-рми: BitMap -> Free();, який звільнить пам’ять після того, як наша програма завершиться.

14. Запрограмуємо обробку меню Відкрити:

if (OpenPictureDialog1->Execute()) { Image3->Picture->LoadFromFile (OpenPictureDialog1->FileName);

BitMap->Assign(Image3->Picture); }

Ці оператори завантажують в компоненту Image3 файл із малюнком, який користувач обирає у діалоговому режимі. Цей файл зра-зу ж записується в BitMap.

15. Запрограмуємо обробку меню Відміна:

Image3-> Picture ->Assign(BitMap);

Оператор відновлює на канві зображення, яке було записане в BitMap.

16. В обробник події OnClick для кнопок SBBrush і SBColor запишемо оператор:

if (((TSpeedButton *) Sender)->Down)

BitMap->Assign(Image3->Picture);

Він запам’ятає в BitMap поточне зображеня після початку роботи з черговим інструментом



Поделиться:


Последнее изменение этой страницы: 2016-08-14; просмотров: 72; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.136.154.103 (0.035 с.)