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

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

Представлена вище функція 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;

}

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