Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
1 (6).doc
Скачиваний:
49
Добавлен:
12.05.2015
Размер:
2 Мб
Скачать

Механізм передачі параметрів

Представлена вище функція F_MAX не дуже зручна для використання, оскільки її призначення зафіксоване дуже жорстко. Зокрема, вхідними даними для неї можуть служити лише значення змінних n1 і n2. Тому перед кожним звертанням до функції доводиться заздалегідь присвоювати цим змінним ті значення, з яких потрібно вибирати більше.

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

Слід зазначити, що параметри використовуються не тільки як інструмент для передачі в підпрограму вихідних даних, а й для повернення у зовнішній блок (основну програму, підпрограму) отриманих результатів.

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

Формальні параметри, якщо вони є, явно вказуються у заголовку підпрограми і тим самим упорядковуються по їх перерахуванню. З урахуванням вищезазначеного формат заголовка функції у С/С++ можна представити наступним чином:

тип_результату ім'я_функції ([список_ формальних_параметрів]).

Конкретизація дій підпрограми здійснюється за допомогою аргументів або фактичних параметрів - конкретних значень або змінних, які повинна обробити підпрограма, і які в її тілі були позначені формальними параметрами. Вказуються фактичні параметри, якщо вони є, в операторі виклику відповідної підпрограми. У С/С++ оператор виклику функції має наступний формат:

ім'я_ функції[(список_фактичних_параметрів)].

Список фактичних параметрів в операторі виклику підпрограми повинен відповідати списку формальних параметрів у заголовку підпрограми. Ця відповідність повинна бути взаємно-однозначною по кількості, порядку і типу параметрів у результаті їхнього перебору зліва направо. Тобто кількість, порядок слідування і тип формальних і фактичних параметрів повинні відповідати однин одному, тобто збігатися.

Таким чином, фактичні параметри - це конкретні значення або змінні, які повинна обробити підпрограма; формальні параметри - це абстрактні імена, в термінах яких описуються дії по обробці фактичних параметрів в тілі підпрограми.

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

Опис формальних параметрів у заголовку підпрограми являє собою їх перелік з вказанням для кожного такого параметра імені типу того значення, яке представляється цим формальним параметром. РБНФ відповідного поняття для мов С/С++:

список_формальних_параметрів = тип ім'я {, тип ім'я}.

Наприклад,

float FUNС(float p1, float p2).

У С/С++ типи формальних параметрів можуть описуватися в заголовку функції або після нього, але до тіла функції:

float FUNС (float p1, float p2)

{ …

}

float FUNС (p1, p2)

float p1; float p2;

{ …

}

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

Для прикладу, змінимо функцію F_MAX, представивши її вхідні дані n1 і n2 у вигляді параметрів. Для цього введемо формальні параметри (ідентифікатори, які не використовуються в тілі функції для інших цілей), наприклад p1 та p2, і запишемо тіло функції з їх використанням:

float F_MAX (float p1, float p2)

{ if (p1>p2) return p1;

else return p2;

}

Після цього головну функцію вихідної програми можна записати так:

// variant 5

int main()

{ float x, y, // вхідні дані

u, v; // результати обчислень

cout <<“Input x, y:”;

cin >> x >> y;

u= F_MAX (x+y, x*y);

v= F_MAX (9.5, u);

cout<<“u=“<<u<<“ v=“<<v<<endl;

system(“pause“);

}

Як видно, тепер в основній програмі відпала необхідність вводити у вживання змінні n1 і n2, а перед зверненням до функції - присвоювати цим змінним відповідні значення. Завдяки цьому головна функція основної програми стала ще більш компактною і наочною.

Згідно з правилами мови програмування в тілі підпрограми звернення до інших підпрограм може з'явитися лише тоді, коли ця підпрограма вже описана раніше. Але, наприклад, у випадку непрямої рекурсії, підпрограми, описані на одному рівні вкладеності, можуть мати взаємні виклики одна одної, наприклад,

float Func1 (float x, float y)

{ Func2 (1, 2);

}

float Func2 (int a, int b);

{ Func1 (0.5, 0.99);

}

У цьому випадку при компіляції функції Func1 компілятор не може правильно обробити виклик функції Func2, оскільки ця функція описується нижче по тексту і інформація про неї ще не відома. Якщо поміняти місцями ці дві функції, то відбувається аналогічна ситуація з компіляцією виклику Func1 у функції Func2.

Вирішенням цієї проблеми є механізм випереджувальних описів підпрограм, який підтримується багатьма мовами програмування. Даний механізм передбачає, що спочатку задається попередній опис підпрограми, який містить необхідну для ідентифікації підпрограми інформацію (зазвичай, заголовок підпрограми з вказанням кількості і типу її параметрів); повний же опис підпрограми розміщується в тексті програми далі. У мові Pascal випереджувальний опис підпрограм реалізується за допомогою директиви forwаrd, у C/C++ для цього служать так звані прототипи функцій.

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

float F_MAX (float, float).

Частину прототипу функції, яка включає її ім’я та типи параметрів називають сигнатурою функції.

Прототипи у С/С++ можна задавати для будь-якої функції користувача, тобто, не обов’язково при взаємних викликах функцій.

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

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

// variant 6

float F_MAX (float, float); // прототип функції

//========== головна функція =============================

int main()

{ float x,y, // вхідні дані

u,v; // результати обчислень

cout <<“Input x, y:”;

cin >> x >> y;

u= F_MAX (x+y, x*y);

v= F_MAX (9.5, u);

cout<<“u=“<<u<<“ v=“<<v<<endl;

system(“pause“);

}

// ======== визначення максимального значення ========

float F_MAX (float p1, float p2)

{ if (p1>p2) return p1;

else return p2;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]