- •Процедурно-орієнтоване програмування Організація підпрограм Поняття підпрограми
- •Організація підпрограм
- •Механізм передачі параметрів
- •Принцип локалізації
- •Концепція розподілу пам’яті
- •Способи передачі параметрів
- •Вказівники на функції
- •Розширені можливості використання підпрограм Функції з аргументами за замовчуванням
- •Перевантаження функцій
- •Шаблони функцій
- •Вбудовані функції
- •Рекурсія
Вказівники на функції
Сучасні мови програмування, зокрема C++, підтримують мехазнім організації вказівників на функції, які зберігають адресу функції (адресу її першого виконуваного оператора).
Загальний синтаксис оголошення вказівника на функцію має вигляд:
тип_результату (*покажчик)(список_параметрів).
Тоді загальний синтаксис виклику функції через вказівник виглядає так:
(*покажчик)( список_параметрів).
При ініціалізації вказівників на функції іменем конкретної функції треба забезпечити відповідність типу, який повертає функція, i cписку її параметрів до оголошення вказівника. Після ініціалізації вказівника на функцію його можна використовувати для виклику цих функцій, наприклад,
int funct1(int, double); // прототип функції funct1
int funct2(int, double); // прототип функції funct2
int main()
{ int (*p)(int, double); // оголошення вказівника на функцію
p= funct1; // організація вказівника на funct1
int i= p(1, 2); // виклик funct1 через вказівник
p= funct2; // переадресація вказівника на funct2
i= p(1,2); // виклик funct2 через вказівник
i= (*p)(1,2); // виклик в старому форматі
system("pause");
}
int funct1(int i1, double i2) // оголошення функції funct1
{ return (i1+ int(i2));
}
int funct2(int i1, double i2) // оголошення функції funct2
{ return (i1- int(i2));
}
Використання вказівника на функцію дає змогу передавати функції як аргументи при виклику інших функцій. Наприклад, треба надрукувати таблиці значень функцій x3–x+1 і ex–3 на відрізку [a, b] із кроком h.
float lower, upper, step; float Polynom(float); float Exponent(float); void Print (float, float, float, float (*)(float));
//========== головна функція =============================
int main() { cout<<“Еnter lower, upper bounds and step"; cin>>lower>>upper>>step;
Print (lower, upper, step, Polynom); Print (lower, upper, step, Exponent); system("pause");
}
// ======== визначення функції Polynom ========
float Polynom (float x)
{ return pow(x, 3)-x+1; }
// ======== визначення функції Exponent ========
float Exponent (float x)
{ return exp(x-3); }
// ======== визначення функції друку Print ========
void Print (float a, float b, float h, float (*func)(float))
{ float x;
cout<<"================== "<<endl;
x=a; while (x<b)
{ printf("%6.1f | %10.6f\n", x, (*func)(x));
x+=h;
}
}
Отримаємо наступний результат:
Для оголошення вказівників на функції рекомендується використовувати директиву typedef за допомогою якої вводиться короткий синонім (псевдоім’я) взамін великих декларативних конструкцій. Наприклад,
typedef void (*type)(void); // визначення імені типу type
type p;
// ======== визначення функції F1 ========
void F1(void)
{ cout <<"F1";
}
// ======== визначення функції F2 ========
void F2(void)
{ cout <<"F2";
}
//========== головна функція =============================
int main()
{ p = F1;
p();
p=F2;
p();
system("pause");
}
Відеокопія результату:
Розширені можливості використання підпрограм Функції з аргументами за замовчуванням
У прототипі функції можна задати не тільки типи, але й значення аргументів. В цьому випадку під час виклику функції кількість переданих їй аргументів може бути менше кількості оголошених параметрів. Значення недостаючих аргументів вибираються із списку оголошення за замовчуванням.
Наприклад, будемо виводити на екран рядки, які містять певну кількість заданих символів:
int main()
{ writechar('*', 10);
writechar('+', 10);
writechar('=', 5);
system("pause");
}
Для реалізації виведення заданого символу певну кількість разів оголосимо функцію writechar() наступного виду:
void writechar(char ch, int n)
{ for (int i=1; i<=n; i++)
cout<<ch;
cout<<endl;
}
Отримаємо наступний результат:
Дану функцію можна оголосити з аргументами за замовчуванням, задавши їх значення при визначенні функції:
void writechar(char ch='*', int n=10)
{ for (int i=1; i<=n; i++)
cout<<ch;
cout<<endl;
}
або у прототипі функції:
void writechar(char ='*', int =10); // прототип функції
…
void writechar(char ch, int n) // оголошення функції
{ for (int i=1; i<=n; i++)
cout<<ch;
cout<<endl;
}
Тоді в результаті виконання наступних викликів даної функції з різними списками аргументів
int main()
{ writechar();
writechar('+');
writechar('=', 5);
writechar(65);
system("pause");
}
отримаємо на екрані:
Під час першого виклику функція не має аргументів: їх значення визначаються з оголошення прототипу. На екрані з’явиться рядок з 10 символів '*'. Другий виклик функції передає їй тільки один аргумент — значення символу. Значення другого аргументу визначається за замовчуванням з визначення функції. На екран виведеться рядок з 10 символів '+'. Третій виклик функції здійснюється із явною передачею значень двох аргументів, тому на екрані буде рядок з 5 символів '='. Під час четвертого виклику функції їй передається числовий параметр, який компілятор вважає кодом символу, що виводитиметься. Кількість цих символів визначається за замовчуванням.
Отже, якщо під час виклику функції кількість переданих їй аргументів менше кількості оголошених у прототипі чи функції, то компілятор вважає, що відсутні останні за списком аргументи. Їх значення вибираються із списку оголошення за замовчуванням.