КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Friend beta
Class beta а потім оголосити клас alpha, а всередині визначення alpha оголосити дружність класу beta
Подібно дружнім класам, можливим є оголошення функцій - друзів - зовнішніх функцій або елементів-функцій іншого класу, що можуть здійснювати безпосередній доступ до всіх елементів та функцій класу, для якого вони дружні, в тому числі, оголошеними як protected та private. Правила опису та особливості дружніх функцій можна подати у такому порядку: § дружня функція оголошується в середині класу, до елементів якого потрібен доступ, з ключовим словом friend. Найчастіше у якості параметра такій функції повинен передаватися сам об'єкт, або посилання на об'єкт класу, оскільки вказівник this їй не передається. § дружня функція може бути звичайною функцією або методом іншого визначеного класу. На цю функцію не поширюються дії специфікаторів доступу, не має значення конкретне місце її розташування у протоколі. § одна функція може бути дружньою по відношенню до декількох класів
Class One { private: char* str; public: One () { Str="123";} friend void Importante (One &a); //оголошення friend - функції void External (One &a); int main (void) { One r; External(r); return 0; } void External (One &a) { cout << a. str<<endl; // доступ до елемента-даних char*str з секції private
Одна й та сама функція може бути оголошеною як friend двом класам одночасно.
У вищенаведеному прикладі функція registration() може застосовуватися як класом Teacher, так і класом Student, не знаходячись у жодному з них, але пов'язуючи їх під час реєстрації (ініціалізації), що цілком нормально, виходячи з даного контексту. Тепер щодо випадку, коли використовуються функції-друзі як елементи-функції. Зазвичай, дружньою у класі оголошується елемент-функція іншого класу. Ця функція матиме вільний доступ до захищеної та закритої частин класу, в якому вона оголошена як friend. На практиці це може виглядати таким чином:
В реалізації видно, як функція show() звертається до закритої частини обох класів, хоча належить лише одному з них - класу В. Слід відмітити, що клас, в якому міститься прототип елемента-функції, повинен оголошуватися раніше класу, що вказує на функцію-елемент як дружню. Так для класу А, який оголошує дружньою для себе функцію B::show(A&c1), оголошення класу В попередньо повинно бути доступним компілятору.
Нехай нам необхідно, щоб функція працювала з об’єктами двох різних класів. Наприклад, функція буде розглядати об’єкти двох класів як аргументи і оброблятиме їх приховані дані. В програмі 22.8 приведено простий приклад FRIEND, що дає уявлення про роботу дружніх функцій в якості мостів між двома класами.
Програма 22.8 В цій програмі ми бачимо два класи – alpha і beta. Конструктори цих класів задають їх єдині елементи даних у вигляді фіксованих значень 3 і 5. Нам необхідно, щоб функція frifunc() мала доступ до тих та інших прихованих даних, тому ми робимо її дружньою функцією. З цією метою всередині кожного класу використане ключове слово friend. friend int frifunc(alpha,beta); Це оголошення може бути розміщене де завгодно всередині класу. Немає жодної різниці, запишемо ми його в public - чи private -секцію. Об’єкт кожного класу передається як параметр функції frifunc(), і функція має доступ до прихованих даних обох класів через ці аргументи. Функція додає значення даних і повертає їх суму. Нагадаємо, що до класу не можна звертатися до того, як він оголошений в програмі. Оголошення функції frifunc() в класі alpha посилається на клас beta, а, отже, beta повинен бути оголошений до alpha. Звідси означення class beta; на початку програми. Треба відмітити, що ідея дружніх функцій дещо сумнівна. Під час розробки С++ на цю тему велися суперечки і приводилися аргументи проти включення в мову такої можливості. З одного боку, дружні функції підвищують гнучкість мови, з іншого - вони не відповідають принципу обмеження доступу до даних, згідно з яким тільки функції-члени можуть мати доступ до прихованих даних класу. Наскільки серйозно суперечить єдності концепції використання дружніх функцій? Дружня функція оголошується такою в тому класі, до даних якого вона пізніше й матиме доступ. Таким чином, програміст, що не має доступу до вихідного коду класу, не може зробити функцію дружньою. В цьому сенсі цілісність даних зберігається. Але все одно такі функції можуть призвести до «spaghetti code» (код з надто великою кількістю передач управління), коли численні дружні функції фактично стирають границі між класами. З цієї причини дружні функції повинні бути принаймні розкидані по програмі і зустрічатися як можна рідше.
Все-таки інколи дружні функції занадто зручні, щоб від них відмовлятися. Найзагальнішим прикладом цього є ситуація, коли вони використовуються для підвищення багатосторонності перезавантажуваних операцій. Програма 22.9 показує обмеженість використання таких операторів без використання дружніх функцій. Програма працює з раніше вже нами використовуваним типом Distance (англійські міри довжини).
Програма 22.9 В цій програмі оператор «+» перевстановлений на додавання двох об’єктів типу Distance. Крім того, наявний конструктор з одним аргументом, який переводить значення типу float в значення типу Distance. Якщо є такий конструктор, то можна записати вираз: d3=10.0+d1; Перезавантаженому + потрібні об’єкти типу Distance справа і зліва, але, знайшовши справа аргумент типу float, у відповідності з конструктором він переводить цей float в Distance і здійснює додавання. Але що трапиться, коли ми переставимо доданки місцями? d3=10.0+d1; Цей вираз не буде оброблений як належить, оскільки об’єкт, чиїм методом є перезавантажений +, повинен бути змінною, що знаходиться зліва від оператора. Коли ми поміщаємо туди операнд іншого типу чи константу, компілятор використає + для додавання з цим типом (в даному випадку float) замість того, щоб додавати об’єкти типу Distance. Але цей оператор не вміє конвертувати float в Distance, тому не може виконати додавання. Вийти з цієї ситуації можна, створивши новий об’єкт типу Distance. d3=Distance(10.)+d1; Такий вираз є цілком коректним, але неелегантним і неочевидним. Як написати звичний для нас вираз, що містив би потрібні типи справа і зліва від оператора? За допомогою дружньої функції. Програма 22.10 демонструє, як саме це зробити.
Програма 22.10 Перезавантажена операція + зроблена дружньою: friend Distance operator+(Distance,Distance); }; //---------------------------------------- Distance operator+(Distance d1,Distance d2) Зверніть увагу, що у попередньому прикладі (програма 22.9) – перезавантажуваний + є методом, а в програмі 22.10 – дружньою функцією. Будучи звичайним методом, + оперував одним з доданків як об’єктом, членом якого він був, а другим – як операндом. Ставши дружньою функцією, + став розглядати обидва об’єкти в якості аргументів. З цієї причини змінні feet та inches з попередньої програми були замінені змінними d1.feet та d1.inches, оскільки цей об’єкт став аргументом. Запам’ятаймо: щоб зробити функцію дружньою, її оголошення всередині класу слід починати з ключового слова friend. Визначення і виклик функції не змінюються.
Інколи дружня функція дозволяє використовувати зрозуміліший синтаксис виклику функції, ніж звичайний метод. Н а п р и к л а д, нехай нам потрібна функція, що підносить до квадрату екземпляр об’єкту типу Distance, що повертає значення в квадратних футах як тип float. Програма 22.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<<”\n Distance=”;dist.showdist(); cout<<”\n Distance^2=”<<sqft<<” кв футів\n”; bioskey(0); return 0; } Програма 22.11 В головній функції програма створює значення Distance, підносить до квадрату і виводить результат на екран. При цьому ми використовуємо вираз sqft=dist.square(); Цей запис є цілком коректний, але значно зрозумілішим був би функціональний запис: sqft=square(dist); Такого ефекту можна досягти, зробивши square() дружньою функцією для класу Distance. Це показано в програмі 22.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; } Програма 22.12 Функція square() в попередній програмі не потребувала аргументів, будучи звичайним методом, натомість в програмі 22.12 їй вже потрібні аргументи. Загалом кажучи, дружня функція потребує на один аргумент більше, ніж метод.
Дата добавления: 2014-01-07; Просмотров: 325; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |