Дружність і функціональний запис 


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



ЗНАЕТЕ ЛИ ВЫ?

Дружність і функціональний запис



Інколи дружня функція дозволяє використовувати зрозуміліший синтаксис виклику функції, ніж звичайний метод. Наприклад, нехай нам потрібна функція, що підносить до квадрату екземпляр об’єкту типу Distance, що повертає значення в квадратних футах як тип float. Програма 13.11 показує, як це можна зробити за допомогою звичайного методу.

 #include<iostream.h>

 #include<conio.h>

 #include<stdio.h>

 #include<bios.h>

 class Distance

 {int feet;

 float inches;

 public:

 Distance():feet(0),inches(0.0)

 {}

 Distance(float fltfeet)

 {feet=(int)fltfeet;

 inches=12*(fltfeet-feet);

 }

 Distance(int ft,float in)

 {feet=ft;inches=in;}

 void showdist()

 {cout<<feet<<”\’-“<<inches<<’\’’;}

 float square();

 };

 //////////////

 float Distance::square()

 {float fltfeet=feet+inches/12;

 float feetsqrd=fltfeet*fltfeet;

 return feetsqrd;

 }

 //////////////

 int main()

 {clrscr();

 Distance dist(3,6.0);

 float sqft;

 sqft=dist.square();

 cout<<”\nDistance=”;dist.showdist();

 cout<<”\nDistance^2=”<<sqft<<” кв футів\n”;

 bioskey(0);

 return 0;

 }

Програма 13.11

В головній функції програма створює значення Distance, підносить до квадрату і виводить результат на екран. При цьому ми використовуємо вираз

sqft=dist.square();

Цей запис є цілком коректний, але значно зрозумілішим був би функціональний запис:

sqft=square(dist);

Такого ефекту можна досягти, зробивши square() дружньою функцією для класу Distance. Це показано в програмі 13.12

 #include<iostream.h>

 #include<conio.h>

 #include<stdio.h>

 #include<bios.h>

 class Distance

 {int feet;

 float inches;

 public:

 Distance():feet(0),inches(0.0)

 {}

 Distance(float fltfeet)

 {feet=(int)fltfeet;

 inches=12*(fltfeet-feet);

 }

 Distance(int ft,float in)

 {feet=ft;inches=in;}

 void showdist()

 {cout<<feet<<”\’-“<<inches<<’\’’;}

friend float square(Distance);

 };

 //////////////

 float square(Distance d)

 {float fltfeet=d.feet+d.inches/12;

 float feetsqrd=fltfeet*fltfeet;

 return feetsqrd;

 }

 //////////////

 int main()

 {clrscr();

 Distance dist(3,6.0);

 float sqft;

 sqft=square(dist);

 cout<<”\nDistance=”;dist.showdist();

 cout<<”\nDistance^2=”<<sqft<<” кв футів\n”;

 bioskey(0);

 return 0;

 }

Програма 13.12

Функція square() в попередній програмі не потребувала аргументів, будучи звичайним методом, натомість в програмі 13.12 їй вже потрібні аргументи. Загалом кажучи, дружня функція потребує на один аргумент більше, ніж метод.

 

Дружні класи

Методи можуть бути перетворені в дружні функції одночасно з перевизначенням всього класу як дружнього. Програма 13.13 показує, як це виглядає на практиці

 #include<iostream.h>

 #include<conio.h>

 #include<stdio.h>

 #include<bios.h>

 /////////////

 class alpha

 {private:

 int data1;

 public:

 alpha():data1(99)

 { }

 friend class beta;

 };

 ///////////////

 class beta

 {public:

 void func1(alpha a) {cout<<”\ndata1=”<<a.data1;}

 void func2(alpha a) {cout<<”\ndata1=”<<a.data1;}

 };

 //////////////

 

 int main()

 {clrscr();

 alpha a;

 beta b;

 b.func1(a);

 b.func2(a);

 cout<<endl;

 bioskey(0);

 return 0;

 }

Програма 13.13

 

Для класу alpha весь клас beta оголошений дружнім. Тепер всі методи класу beta мають доступ до прихованих даних класу alpha.

Ми оголосили клас дружнім, використовуючи вираз:

friend class beta;

Можна було вчинити інакше: спершу оголосити звичайний клас beta

class beta

а потім оголосити клас alpha, а всередині визначення alpha оголосити дружність класу beta

friend beta

 

Статичні функції

При вивченні теми «Об’єкти і класи» (лекції 11-13) ми ввели поняття статичних даних класу (програма 11.8). Нагадаємо, що статичні дані не дублюються для кожного об’єкту, швидше, один елемент даних використовується всіма об’єктами класу. В тій же програмі був показаний клас, який запам’ятовував, скільки в нього було об’єктів. Спробуємо розвинути цю ідею, показавши, що функції, як і дані, теж можуть бути статичними. Крім демонстрації статичних функцій, наша програма створить клас, який дозволить присвоювати унікальний ідентифікаційний номер (ID) кожному зі своїх об’єктів. Це дозволяє запитати в об’єкта, хто він такий, що буває корисним при відлагодженні програми. Ще одна задача цього прикладу полягає в тому, щоб пролити світло на деструктори і роботу з ними.

 #include<iostream.h>

 #include<conio.h>

 #include<stdio.h>

 #include<bios.h>

 /////////////////

 class gamma

 {private:

 static int total;

 int id;

 public:

 gamma()

 {total++;

 id=total;

 }

 ~gamma()

 {total--;

 cout<<”Видалення ID”<<id<<endl;

 }

  static void showtotal()

 {cout<<”Всього:”<<total<<endl;

 }

 void showid()

 {cout<<”ID:”<<id<<endl;

 }

 };

 ////////////////

 int gamma::total=0;

//////////////////

 

 int main()

 {clrscr();

 gamma g1;

 gamma::showtotal();

 gamma g2,g3;

 gamma::showtotal();

 g1.showid();

 g2.showid();

 g3.showid();

 cout<<»------------endofprogram------\n»;

 return 0;

 }

Програма 13.14

 

 

Доступ до статичних функцій

В приведеній програмі наявний статичний елемент даних з іменем total, що належить класу gamma. В цій змінній зберігається інформація про те, скільки об’єктів створено в класі. ЇЇ значення збільшується конструктором і зменшується деструктором.

Припустимо, що нам потрібно мати доступ до total, знаходячись поза класом. В лістінгу можна побачити функцію showtotal(), яка показує значення цієї змінної. Як одержати до неї доступ?

Якщо певний елемент даних оголошується статичним, на весь клас виділяється єдина копія цього елемента, при цьому неістотно, скільки об’єктів класу ми створили. Насправді може взагалі не бути ніяких об’єктів, але нам цікаво дізнатися навіть про цей факт. Можна створити об’єкт тільки для того, щоб мати можливість викликати потрібний метод, як в приведених далі рядках:

gamma dobj;

dobj.showtotal();

але це і негарно, і нераціонально. За правилами хорошого тону, не слід звертатися до об’єкта, якщо ми робимо що-небудь таке, що стосується класу в цілому. Доцільніше просто використати ім’я класу і оператор явного задання функції:

gamma::showtotal();

Тим не менше, такий прийом не спрацює, якщо showtotal() – звичайний метод. В цьому випадку дійсно доведеться написати ім’я об’єкту, крапку і назву функції. Якщо ж ми хочемо мати доступ до showtotal(), використовуючи тільки ім’я класу, оголосімо її статичною. В програмі 13.14 ми зробили це так:

Static void showtotal()

Оголошена таким способом функція матиме доступ просто через ім’я класу.

 

Нумерація об’єктів

В клас gamma ми помістили ще одну функцію, призначену для виведення ідентифікаційних номерів його об’єктів. Ці ID рівні змінній total в момент створення об’єкта, так що номер кожного об’єкту виявляється унікальним. Функція showid() виводить ID свого об’єкта.

 

Деструктори

Після того, як ми дізналися, що об’єкти можна нумерувати, покажемо одну цікаву властивість деструкторів. Програма 13.14 виводить на екран повідомлення «endofprogram» при завершенні програми. Але, як показує приклад роботи програми, після цього ще дещо відбувається. А саме: три об’єкти, які були створені в процесі роботи програми, повинні бути видалені до її завершення, щоб відновився доступ до пам’яті. Про це потурбується компілятор, виконуючи деструктор.

Вставивши в деструктор вираз, який виводить на екран повідомлення, ми можемо спостерігати за процесом його роботи. Завдяки введеній нумерації ми можемо також спостерігати, в якому порядку видаляються об’єкти. Як бачимо, видалення відбувається в порядку, протилежному до створення. Можна припустити, що локальні об’єкти зберігаються в стеку.



Поделиться:


Последнее изменение этой страницы: 2021-12-15; просмотров: 36; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

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