Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ООП_Навч_посібник.doc
Скачиваний:
8
Добавлен:
01.07.2025
Размер:
6.58 Mб
Скачать

7.2. Передача покажчиків і масивів як аргументів функціям

Дотепер у прикладах, наведених тут, функціям передавалися значення простих змінних. Але можливі ситуації, коли як аргументи необхідно використовувати покажчики і масиви. Вивченню особливостей передачі таких аргументів функцій і присвячено наступні підрозділи.

7.2.1. Виклик функцій з покажчиками

У мові програмування C++ дозволено передавати функції покажчики як аргументи. Для цього достатньо оголосити параметр типу покажчика. Розглянемо такий приклад.

Код програми 7.6. Демонстрація механізму передачі функції покажчика: початкова версія

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

void fun(int *jzm);

int main()

{

int izm;

int *p;

p = &izm; // Покажчик p тепер містить адресу змінної izm.

fun(p);

cout << izm; // Змінна izm тепер містить число 100.

getch(); return 0;

}

void fun(int *jzm)

{

*jzm = 100; // Змінній, яка адресується покажчиком jzm,

// присвоюється число 100.

}

Як бачите, у цій програмі функція fun() приймає один параметр: покажчик на цілочисельне значення. У функції main() покажчику р присвоюється адреса змінної izm. Потім з функції main() викликається функція fun(), а покажчик р передається їй як аргумент. Після того, як параметр-покажчик jzm набуде значення аргументу р, він (так само, як і р) указуватиме на змінну izm, що визначається у функції main(). Таким чином, у процесі виконання операції присвоєння *jzm = 100; змінна izm набуває значення 100. Тому програма відобразить на екрані число 100. У загальному випадку наведена тут функція fun() присвоює число 100 змінній, адреса якої була передана цій функції як аргумент.

У попередньому прикладі необов'язково було використовувати змінному р. Замість неї під час виклику функції fun() достатньо використовувати змінну izm, якій передував оператором "&" (при цьому, як уже зазначалося вище, генерується адреса змінної izm). Після внесення зумовленої зміни попередня програма набуває такого вигляду:

Код програми 7.7. Демонстрація механізму передачі покажчика функції: виправлена версія

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

void fun(int *jzm);

int main()

{

int izm;

fun(&izm);

cout << izm;

getch(); return 0;

}

void fun(int *jzm)

{

*jzm = 100; // Змінній, яка адресується покажчиком jzm,

// присвоюється число 100.

}

Передаючи покажчик функції, необхідно розуміти таке. У процесі виконання деякої операції у функції, яка використовує покажчик, ця операція фактично виконується над змінною, яка адресується цим покажчиком. Таким чином, така функція може змінити значення об'єкта, яка адресується її параметром.

7.2.2. Виклик функцій з масивами

Якщо масив є аргументом функції, то необхідно розуміти, що під час виклику такої функції їй передається тільки адреса першого елемента масиву, а не повна його копія1. Це означає, що оголошення параметра повинно мати тип, сумісний з типом аргумента. Взагалі існує три способи оголосити параметр, який приймає покажчик на масив. По-перше, параметр можна оголосити як масив, тип і розмір якого збігається з типом і розміром масиву, використовуваного під час виклику функції. Цей варіант оголошення параметра-масиву продемонстровано в наведеному нижче прикладі.

Код програми 7.8. Демонстрація способу оголошення параметра-масиву

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

void display(int num[10]);

int main()

{

int t[10], i;

for(i=0; i<10; ++i) t[i] =i;

display(t); // Передаємо функції масив t.

getch(); return 0;

}

// Функція виводить усі елементи масиву.

void display(int num[10])

{

int i;

for(i=0; i<10; i++) cout << num[i]<< "\n";

}

Незважаючи на те, що параметр num оголошений тут як цілочисельний масив, що складається з 10 елементів, С++-компілятор автоматично перетворить його в покажчик на цілочисельне значення. Необхідність цього перетворення пояснюється тим, що ніякий параметр насправді не може прийняти масив цілком. А оскільки буде переданий один тільки покажчик на масив, то функція повинна мати параметр, здатний прийняти цей покажчик.

Другий спосіб оголошення параметра-масиву полягає в його представленні у вигляді безрозмірного масиву, як це показано нижче:

void display(int num[])

{

int i;

for(i=0; i<10; i++) cout << num[i] << "\n";

}

У цьому записі параметр num оголошується як цілочисельний масив невідомого розміру. Оскільки мова C++ не забезпечує перевірки порушення меж масиву, то реальний розмір масиву не релевантний чинник для подібного параметра (але, безумовно, не для програми в цілому). Цілочисельний масив при такому способі оголошення також автоматично перетвориться С++-компілятором у покажчик на цілочисельне значення.

Нарешті, розглянемо третій спосіб оголошення параметра-масиву. Під час передачі масиву функції її параметр можна оголосити як покажчик. Якраз цей варіант найчастіше використовують професійні програмісти. Ось приклад:

void display(int *num)

{

int i;

for(i=0; i<10; i++) cout << num[i]<< "\n";

}

Можливість такого оголошення параметра (у цьому випадку num) пояснюється тим, що будь-який покажчик (подібно до масиву) можна індексувати за допомогою символів квадратних дужок ([]). Таким чином, всі три способи оголошення параметра-масиву приводяться до однакового результату, який можна виразити одним словом: покажчик.

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

Код програми 7.9. Демонстрація оброблення елемента масиву, що використовується як аргумент, подібно до звичайної змінної

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

void display(int num);

int main()

{

int tMas[10], i;

for(i=0; i<10; ++i) tMas[i] =i;

for(i=0; i<10; i++) display(tMas[i]);

getch(); return 0;

}

// Функція виводить одне число.

void display(int num)

{

cout << num << "\n";

}

Як бачите, параметр, який використовується функцією display(), має тип int. Тут не важливо, що ця функція викликається з використанням елемента масиву, оскільки їй передається тільки один його елемент.

Необхідно пам'ятати! Коли масив використовується як аргумент функції, то функції передається адреса цього масиву. Це означає, що код функції може потенційно з|мінити| реальний вміст масиву, використовуваного під час виклику функції.

Наприклад, у наведеному нижче коді програми функція Cube() перетворить значення кожного елемента масиву в куб цього значення. Під час виклику функції Cube() як перший аргумент необхідно передати адресу масиву значень, що підлягають перетворенню, а як друге – його розмір.

Код програми 7.10. Демонстрація перетворення значень елементів масиву

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

void Cube(int *n, int num);

int main()

{

int i, tMas[10];

for(i=0; i<10; i++) tMas[i] = i+1;

cout << "Початковий вміст масиву: ";

for(i=0; i<10; i++) cout << tMas[i] << "\n";

cout << "\n";

Cube(tMas, 10); // Обчислюємо куби значень.

cout << "Змінений вміст: ";

for(i=0; i<10; i++) cout << tMas[i] << "\n";

getch(); return 0;

}

void Cube(int *n, int num)

{

while(num) {

*n = *n * *n * *n;

num--;

n++;

}

}

Результати виконання цієї програми є такими:

Початковий вміст масиву: 1 2 3 4 5 6 7 8 9 10

Змінений вміст: 1 8 27 64 125 216 343 512 729 1000

Як бачите, після звернення до функції Cube() вміст масиву tMas змінився: кожен елемент став таким, що дорівнює кубу початкового значення. Іншими словами, елементи масиву tMas були модифіковані настановами, які є складовими тіла функції Cube(), оскільки її параметр п вказує на масив tMas.