Структури. Частина 4. Структури і функції. Передача структури у функцію в середовищі CLR. Повернення структури з функції
Зміст
- 1. Які існують способи передачі структури у функцію?
- 2. Які існують способи повернення функцією структури?
- 3. Приклад передачі native-структури у функцію за значенням
- 4. Приклад передачі native-структури у функцію за покажчиком
- 5. Як передати у функцію managed-структуру, яка оголошена з кваліфікатором ref? Приклад
- 6. Як передати у функцію managed-структуру, яка оголошена з кваліфікатором value? Приклад
- 7. Як повернути екземпляр native-структури з функції? Приклад
- 8. Приклад повернення з функції покажчика на native-структуру
- 9. Як повернути екземпляр value-структури з функції?
- 10. Приклад повернення покажчика (^) на value-структуру
- 11. Приклад повернення з функції структури, яка оголошена з кваліфікатором ref
- Зв’язані теми
Пошук на інших ресурсах:
1. Які існують способи передачі структури у функцію?
Існує 2 способи передачі native-структури у функцію:
- передача структури за значенням. При такій передачі робиться копія структурної змінної в пам’яті. Якщо структура має великий розмір, то такий спосіб неефективний. Перевагою цього способу є те, що всі маніпуляції з копією структури у функції не впливають на вихідну змінну;
- передача покажчика на структуру. У цьому випадку передається тільки покажчик на структуру. Якщо структура займає великий об’єм пам’яті, то такий спосіб забезпечує швидку передачу значень структурної змінної у функцію. Це пов’язано з тим, що не робиться в пам’яті копії структурної змінної. Недоліком цього способу є те, що у функції випадково можна змінити значення вихідної структурної змінної, коли цього не потрібно робити.
2. Які існують способи повернення функцією структури?
Так само, як і при передачі native-структури у функцію (див. п.1), існують 2 способи повернення:
- повернення структури за значенням;
- повернення покажчика на структуру.
Переваги і недоліки кожного способу такі самі, як описується в п. 1.
3. Приклад передачі native-структури у функцію за значенням
Нехай у модулі “MyStruct.h” дано оголошення native-структури:
// native-структура, що описує точку на координатній площині struct MyPoint { int x; int y; };
Нехай в деякому класі оголошується функція EqualPoints(), яка порівнює дві точки на координатній площині. Функція повертає true, якщо точки еквівалентні (рівні). В іншому випадку функція повертає false.
// функція, що порівнює на рівність дві точки public: bool EqualPoints(MyPoint p1, MyPoint p2) { bool f = false; if ((p1.x == p2.x) && (p1.y == p2.y)) f = true; return f; }
Тоді використання функції EqualPoints() може бути таким:
// підключення модуля "MyStruct.h" #include "MyStruct.h" ... // передача native-структури у функцію за значенням bool f_equal; MyPoint pt1, pt2; // p1, p2 – змінні типу "структура" // заповнення значеннями pt1.x = 23; pt1.y = 35; pt2.x = 23; pt2.y = 35; f_equal = this->EqualPoints(pt1, pt2); // f_equal = true pt1.x = 100; f_equal = EqualPoints(pt1, pt2);
4. Приклад передачі native-структури у функцію за покажчиком
Нехай задано native-структуру:
// native-структура struct MyPoint { int x; int y; };
Нижче наведена функція, яка порівнює на рівність значення структурних змінних. Функція отримує покажчик на структуру.
// передача покажчика на структуру MyPoint bool EqualPointsP(MyPoint * p1, MyPoint * p2) { bool f = false; if ((p1->x == p2->x) && (p1->y == p2->y)) f = true; return f; }
Програмний код, який демонструє використання функції EqualPointsP().
// Передача структури за покажчиком MyPoint p1; MyPoint p2; bool f_equal; p1.x = 28; p1.y = 35; p2.x = 28; p2.y = 35; f_equal = EqualPointsP(&p1, &p2); // f_equal = true p2.y = 100; f_equal = EqualPointsP(&p1, &p2); // f_equal = false
5. Як передати у функцію managed-структуру, яка оголошена з кваліфікатором ref? Приклад
Нехай задано наступну ref-структуру.
// ref-структура ref struct MyPointRef { int x; int y; };
Структури з кваліфікатором ref є структурами посилального типу. Для таких структур пам’ять повинна виділятись з допомогою утиліти gcnew. Тому, у функцію можна передати тільки посилання на такі структури.
Нехай дано функцію LengthRef(), яка визначає довжину лінії, яка з’єднує 2 точки. Функція отримує дві ref-структури в якості параметрів.
// Функція, що визначає довжину між двома точками float LengthRef(MyPointRef ^p1, MyPointRef ^p2) { float l; l = Math::Sqrt((p1->x-p2->x)*(p1->x-p2->x) + (p1->y-p2->y)*(p1->y-p2->y)); return l; }
Використання функції LengthRef() в деякому програмному коді.
// передача ref-структури у функцію MyPointRef ^ pt1; MyPointRef ^ pt2; float len; // виділення пам'яті для ref-структур pt1 = gcnew MyPointRef; pt2 = gcnew MyPointRef; // заповнення ref-структур значеннями pt1->x = 35; pt1->y = 35; pt2->x = 40; pt2->y = 40; len = LengthRef(pt1, pt2); // len = 7.071068
6. Як передати у функцію managed-структуру, яка оголошена з кваліфікатором value? Приклад
Managed-структуру, оголошену з кваліфікатором value можна передати у функцію одним з двох способів:
- за значенням;
- за покажчиком.
Нижче наведено обидва способи для value-структури MyPointValue, яка має таке оголошення.
// value-структура value struct MyPointValue { int x; int y; };
Спосіб 1.
Нехай задана функція LengthValue(), яка визначає відстань між двома точками. Функція отримує вхідним параметром дві структури типу MyPointValue. Структури передаються як параметри-значення.
// визначення відстані між двома точками float LengthValue(MyPointValue p1, MyPointValue p2) { float len; len = (float)Math::Sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)); return len; }
Приклад використання функції LengthValue() у програмі.
// передача value-структури за значенням MyPointValue pt1; MyPointValue pt2; float len; pt1.x = 35; pt1.y = 50; pt2.x = 40; pt2.y = 55; len = LengthValue(pt1, pt2); // len = 7.071068
Спосіб 2. Передача структури за покажчиком.
Нехай задана функція LengthValueP(), яка отримує два покажчики на структури типу MyPointValue.
// функція отримує покажчик на value-структуру float LengthValueP(MyPointValue *p1, MyPointValue *p2) { float len; len = Math::Sqrt((p1->x-p2->x)*(p1->x-p2->x) + (p1->y-p2->y)*(p1->y-p2->y)); return len; }
Використання функції LengthValueP() у програмі.
// передача value-структури за покажчиком MyPointValue pt1; MyPointValue pt2; float len; pt1.x = 0; pt1.y = 0; pt2.x = 10; pt2.y = 10; len = LengthValueP(&pt1, &pt2); // len = 14.14214
7. Як повернути екземпляр native-структури з функції? Приклад
Повернути native-структуру можна:
- за значенням;
- за адресою.
Нехай задано структуру MyPoint
// native-структура struct MyPoint { int x; int y; };
Нехай у програмі реалізовано функцію GetCenterLine(), яка обчислює координати середини відрізку, що з’єднує 2 точки. Функція отримує 2 параметри – координати кінців відрізка.
// функція, що повертає native-структуру // функція обчислює координати середини відрізку MyPoint GetCenterLine(MyPoint p1, MyPoint p2) { MyPoint res; res.x = (p1.x + p2.x)/2; res.y = (p1.y + p2.y)/2; return res; }
Демонстрація повернення native-структури за значенням.
MyPoint pt1; MyPoint pt2; MyPoint resP; // результуюча точка, пам'ять має бути виділена pt1.x = 30; pt1.y = 20; pt2.x = 36; pt2.y = 40; resP = GetCenterLine(pt1, pt2); // resP - координати середини відрізка
8. Приклад повернення з функції покажчика на native-структуру
Нехай задано структуру MyPoint
// native-структура struct MyPoint { int x; int y; };
Нехай реалізовано функцію GetCenterLineP(), яка отримує 2 точки і повертає покажчик на структуру. У тілі функції реалізовано виділення пам’яті для структури оператором new.
MyPoint * GetCenterLineP(MyPoint p1, MyPoint p2) { MyPoint * resP; // покажчик на структуру MyPoint // виділення пам'яті для структури динамічно resP = new MyPoint; // обчислення середини відрізку - заповнення значеннями resP->x = (p1.x + p2.x)/2; resP->y = (p1.y + p2.y)/2; return resP; }
Демонстрація роботи з функцією GetCenterLineP().
// повернення native-структури за покажчиком MyPoint * resPt; // покажчик на структуру – пам’ять для структури ще не виділена MyPoint pt1, pt2; // екземпляри структури pt1.x = 28; pt1.y = 40; pt2.x = 38; pt2.y = 50; // виклик функції GetCenterLineP() // для покажчика resPt пам'ять виділяється всередині функції resPt = GetCenterLineP(pt1, pt2); // перевірка int d; d = resPt->x; // d = 33 d = resPt->y; // d = 45
9. Як повернути екземпляр value-структури з функції?
Якщо в середовищі CLR описана структура з кваліфікатором value, то повернення екземпляру такої структури з функції нічим не відрізняється від повернення native-структури (див. п. 7.).
10. Приклад повернення покажчика (^) на value-структуру
Якщо структура оголошена з кваліфікатором value, то функція може повертати покажчик на цю структуру. Допускається використання двох видів покажчиків:
- класичного покажчика, який позначається символом ‘*’. Повернення такого покажчика з функції не відрізняється від повернення покажчика на native-структуру (див. п. 8);
- покажчика, призначеного для роботи з об’єктами середовища CLR. Такий покажчик позначається символом ‘^’. Пам’ять для такого покажчика виділяється утилітою gcnew. Нижче наведено приклад повернення з функції такого покажчика на value-структуру.
Нехай оголошено структуру з кваліфікатором value
// value-структура value struct MyPointValue { int x; int y; };
Нехай потрібно реалізувати функцію GetCenterLineVP(), яка отримує 2 точки і повертає покажчик на результуючу value-структуру. Результуюча структура містить координати центру відрізку, що з’єднує точки. Функція має такий вигляд:
// функція повертає покажчик на value-структуру MyPointValue ^ GetCenterLineVP(MyPointValue p1, MyPointValue p2) { MyPointValue ^ pv; // покажчик на структуру MyPointValue pv = gcnew MyPointValue; pv->x = (p1.x + p2.x)/2; pv->y = (p1.y + p2.y)/2; return pv; }
Демонстрація виклику функції з іншого програмного коду:
// створення екземплярів структур з одночасною ініціалізацією MyPointValue pt1 = { 20, 30 }; MyPointValue pt2 = { 40, 60 }; // покажчик на структуру MyPointValue MyPointValue ^ resPt; // виклик функції GetCenterLineVP() // всередині функції виділяється пам'ять для структури, // на яку вказує resPt resPt = GetCenterLineVP(pt1, pt2); // перевірка int d; d = resPt->x; // d = 30 d = resPt->y; // d = 45
11. Приклад повернення з функції структури, яка оголошена з кваліфікатором ref
Для структури, що оголошена з кваліфікатором ref є певні особливості використання. Така структура є структурою посилального типу. Тому функція повинна повертати посилання на таку структуру (покажчик ^ на структуру). Повернути екземпляр ref-структури (за значенням) з функції не вдасться (див. п. 5).
Нехай оголошено структуру
// ref-структура ref struct MyPointRef { int x; int y; };
Тоді функція, що отримує 2 точки в якості параметрів і знаходить центр між двома точками буде мати приблизно наступний вигляд:
// функція, що повертає ref-структуру MyPointRef ^ GetCenterLineRef(MyPointRef ^p1, MyPointRef ^p2) { MyPointRef ^resPt; // виділення пам’яті для покажчика resPt resPt = gcnew MyPointRef; // заповнення значеннями полів покажчика resPt->x = (p1->x + p2->x)/2; resPt->y = (p1->y + p2->y)/2; return resPt; }
Демонстрація використання функції в іншому програмному коді.
// покажчики на ref-структуру MyPointRef ^pt1; MyPointRef ^pt2; MyPointRef ^resPt; // виділення пам'яті для покажчиків pt1, pt2 pt1 = gcnew MyPointRef; pt2 = gcnew MyPointRef; // заповнення значеннями pt1->x = 20; pt1->y = 20; pt2->x = 30; pt2->y = 40; // виклик функції GetCenterLineRef() // пам'ять для покажчика resPt виділяється всередині функції resPt = GetCenterLineRef(pt1, pt2); // перевірка int d; d = resPt->x; // d = 25 d = resPt->y; // d = 30
Зв’язані теми
- Структури. Частина 1. Складені типи даних. Шаблон структури. Структурна змінна. Структури в середовищі CLR. Оголошення та ініціалізація структурної змінної
- Структури. Частина 2. Виділення пам’яті для структури. Вкладені структури. Масиви native-структур
- Структури. Частина 3. Робота з managed-структурами в середовищі CLR. Кваліфікатори ref і value. Оголошення структурних змінних. Масиви managed-структурних змінних. Ініціалізація managed-структур
- Функції. Частина 1. Опис функції. Фактичні та формальні параметри. Передача параметрів у функцію за значенням та за адресою
- Функції. Частина 2. Функції і масиви. Передача одновимірного та багатовимірного масиву в функцію. Передача структури і класу в функцію