Єдина Країна!

Головне меню

Наша кнопка

Українські уроки про ІТ

Друзі

Підтримка української армії


Головна Програмування - C++ Базовий курс програмування на С++. Урок 11. Вбудовані функції. Inline та Define. Шаблони та перевантаження функцій

Базовий курс програмування на С++. Урок 11. Вбудовані функції. Inline та Define. Шаблони та перевантаження функцій
Написав Joker   
Понеділок, 14 вересня 2015 07:28
Переглядів: 6824

Інколи саме ті хто, здавалося б,

нічого з себе не представляє,

робить те, що ніхто й уявити не міг.

Фільм “Гра в імітацію”

Сьогодні ми розглянемо:

1. Розв’язок д/з минулого уроку

2. Inline

3. Define

4. Шаблони функцій

5. Перевантаження функцій

 

 

 

Розв'язок д/з з попереднього уроку

1. Напишіть функцію для пошуку факторіалу.

#include <iostream>
#include <conio.h>
using namespace std;
 
int Factorial (int n);
 
int main ()
{
	int a;
	cout<< "Enter a --> ";
	cin>> a;
 
	cout<< "Result = " << Factorial(a) <<endl;
 
	_getch();
	return 0;
}
 
int Factorial (int n)
{
	if (n==0)
	return 1;
	return Factorial(n-1) * n;
}


2. Програму яка містить:

2.1. Функцію заповнення масиву з 5 елементів (заповнення рандомно від 0 до 10)

2.2. Функцію яка знаходить елемент, який повторюється найчастіше

 
/*
Цей алгоритм не є найефективнішим із усіх можливих, тобто цю проблему можна розв'язати ефективнішим методом.
Проте, ця версія є найпростішою і кожен мав прийти хоча б до такого рішення.
*/
#include <iostream>
#include <conio.h>
#include <algorithm>
#include <vector>
#include <time.h>
#include <stdlib.h>
using namespace std;
 
void Fill (int n[], int len);
int Popular (int n[], int m[], int len);
 
int main ()
{
	srand(time(NULL));
	const short int size = 5;
	int a[size], m[size];         // m[size] для зберігання популярності кожного з чисел
 
	Fill (a,size);
	cout<< "Resultis = " <<Popular(a,m,size) <<endl;
 
	_getch();
	return 0;
}
 
Void Fill (int n[], int len)
{
	cout<< "\n" << "Firstarray: ";
	for (int i=0; i<len; ++i)
	{
		n[i] = rand() % 10;
		cout<< n[i] << "\t";
	}
	cout<<endl;
}
 
int Popular (int n[], int m[], int len)
{
	int count = 0;
	for (int i=0; i<len; ++i)
	{
		for (int j=i; j<len; ++j)
		{
			if (n[i] == n[j])
				count++;
		}
		m[i] = count;
		count=0;
	}
 
	int Max = m[0];                // якщо подумати, ця змінна не є обов'яковою
	int index = 0;
	for (int i=0; i<len; i++)
	{
		if (Max< m[i])
		{
			Max = m[i];
			index = i;
		}
	}
 
	return n[index];
}


 

3. Функцію – конвертер валют. Функція має 2 аргументи. Перший аргумент – числове значення суми валюти. Якщо другий аргумент = 1, то перевести гривні у долари. Якщо другий елемент = 0, то перевести долари у гривні. Курс валют взяти за останній на момент написання д/з.

// 24/06/15        Конвертер валют
// 1 Usd = 21.17 UAH
#include <iostream>
#include <conio.h>
using namespace std;
 
double Convert (double a, bool key);
 
int main ()
{
	setlocale(LC_CTYPE, "ukr");
 
	int sum;
	bool temp;
 
	cout<< "\n" << "Виберiть опцiю: " <<endl;
	cout<< "\n" << " Конвертувати долари (USD) у гривнi (UAH) - 0" <<endl;
	cout<< "\n" << " Конвертувати гривнi (UAH) у долари (USD) - 1" <<endl;
 
	cout<< "\n\n" << "Ваш вибiр --> ";
	cin>>temp;
 
	cout<< "\n" << "Введiть суму --> ";
	cin>>sum;
 
	cout<<Convert(sum, temp) <<endl;
	_getch();
	return 0;
}
 
double Convert (double a, bool key)
{
	Const double NBU = 21.17;
 
	if (key) {
		cout<< "Результат конвертування (USD) = ";
		return a / NBU;
	}
	else {
		cout<< "Результат конвертування (UAH) = ";
		return a * NBU;
	}
}
 

 

Вбудовані функції

Inline

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

Проте існують ще інші види функцій. Перший з яким ми познайомимось – вбудовані функції. Коли компілятор бачить виклик такої функції, він вбудує (скопіює) її на місце виклику. Це зменшить час опрацювання. Все це робиться за допомогою специфікатора inline.

Приклад такої програми:

#include <iostream>
#include <conio.h>
using namespace std;
 
inline int func(int b)
{
	return b*b;
}
 
int main()
{
	int a;
	cout<< "Enter a --> ";
	cin>> a;
	cout<< "res = " <<func(a) <<endl;
 
	_getch();
	return 0;
}

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

Але є випадки коли компілятор ігнорує inline.Здебільшого причини такі:

1)    Функція рекурсивна

2)    Функція містить if або switch

3)    Занадто великий розмір функції

 

Define

Inline не є єдиним методом вбудовувати в програму фрагмент коду, який повторюється. В цьому нам допоможе define. Розглянемо все на прикладі.

#include <iostream>
#include <conio.h>
using namespace std;
 
#define Pow(x) (x*x)
 
int main ()
{
	int a;
	cout<< "Enter a --> ";
	cin>> a;
 
	cout<<Pow(a) <<endl;
 
	_getch();
	return 0;
}

 

Спершу ви повинні замітити, що директива #define не в функції main. Далі варто помітити, що відсутній символ ;. Pow– ім’я, в перших дужках містяться параметри (x), а останні дужки взагалі не є обов’язковими.

Ця програма підносить змінну aдо квадрату. Але як вона це робить? Компілятор зустрівши Pow замінює цей вираз на той, що в останній дужках. Але навіщо зайві дужки, якщо все працює без них? Вся логіка у пріоритетності. Давайте оновимо нашу програму до такої:

#include <iostream>
#include <conio.h>
using namespace std;
 
#define Pow(x) x*x
 
int main ()
{
	int a;
	cout<< "Enter a --> ";
	cin>> a;
 
	cout<<Pow(a+8) <<endl;
 
	_getch();
	return 0;
}

 

Все працює, але проблема в тому як працює.

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

#include <iostream>
#include <conio.h>
using namespace std;
 
#define a(x) 10
#define ok 1
 
int main ()
{
	cout<< "#define a = " << a(1) <<endl;
	cout<< "#defineok = " <<ok<<endl;
 
	if (a(0) <ok)
		cout<< "a <ok " <<endl;
	else
		cout<< "a >ok" <<endl;
 
	_getch();
	return 0;
}

В даному випадку a має параметр, але від нього нічого не залежить і значення не зміниться. В таких випадках його можна опустити (як у випадку з ok).

 

Шаблони функцій

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

Шаблони функцій дозволяють створити одну функцію яка працює для різних типів даних.

Ця функція повертає модуль числа:

template <typename T> T Abs (T N)
{
	return N < 0 ? -N : N;
}

Ідентифікатор T – параметр типу. Саме він визначає, який тип йому використовувати. Якщо в функцію передати значення типу int, то наша функція буде рівносильна такій:

int Abs (int n)
{
	return N < 0 ? -N : N;
}

Процес створення компілятором екземпляра функції для любого типу – створення екземпляру шаблону функції. При створенні шаблону ми використовуємо специфікатори template, typename. Замість T можна ввести будь-яке інше ім’я. Ну і в круглих дужках можна ввести більше одного параметра.

Ми створюємо функцію з універсальним типом, а компілятор вже сам визначить, яким типом користуватися замість T. Але варто памятати, що замість T можна підставити тільки один тип. Для прикладу напишемо шаблон для пошуку максимуму:

template <typename T> T Max (T a, T b)
{
	return a < b ? b : a;
}

Перший параметр a і другий – b повинні бути одного типу. В даному випадку ми можемо викликати цю функцію таким чином:

cout<<Max (5, 7) <<endl;
cout<<Max (6.45,  4.2) <<endl;
cout<<Max ('b', 'z') <<endl;
// Помилка
cout<<Max (5,  4.123);

Але цю проблему можна легко вирішити:

template<typename T, typename Z> Z Max(T A , Z B)
{
	return A > B ? A : B;
}

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

template <typename T, typename T2> T Max (T a, T b);                              // Помилка

 

Перезавантаження функцій

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

Ось приклад програми:

#include <iostream>
#include <conio.h>
#include <time.h>
#include <stdlib.h>
using namespace std;
 
long Max (int len, int n[])
{
	long type = n[0];
	for (int i(1); i<len; ++i)
		type = type< n[i] ? n[i] : type;
	cout<< "long Max = ";
	return type;
}
float Max (int len, float n[])
{
	float type = n[0];
	for (int i(1); i<len; ++i)
		type = type< n[i] ? n[i] : type;
	cout<< "float Max = ";
	return type;
}
double Max (int len, double n[])
{
	double type = n[0];
	for (int i(1); i<len; ++i)
		type = type< n[i] ? n[i] : type;
	cout<< "double Max = ";
	return type;
 
}
 
 
int main ()
{
	srand(time(NULL));
	const short int size = 5;
 
	int x[size] = {5, 60, 34, 0, 12};
	float f[size] = {1.6, 2.6, 3.5, 15.1, 0.2};
	double d[size] = {1.006, 2.123, 3.147, 28.0089, 0.3124};
 
	cout<<Max(size, x) <<endl;
	cout<<Max(size, f) <<endl;
	cout<<Max(size, d) <<endl;
 
	_getch();
	return 0;
}

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

 

Домашнє завдання

1. Написати шаблон функцій для пошуку середнього арифметичного значення масиву.
2. Написати функцію, яка здійснює округлення певного числа з заданою точністю.
3. Написати перевантажені шаблони функцій для пошуку коренів лінійного (ax + b = 0) та квадратного (ax2+bx+c=0)  рівнянь. У функцію передавати коефіцієнти.

 

P.S. Smile


( 9 Проголосувало )

Схожі статті:
Новіші матеріали:
Старіші матеріали:

Коментарі
Добавити новий
sasha  - Функції   |2019-02-06 23:08:07
Навіщо взагалі створювати прототипи
функції, якщо їх просто можна описати в main?
І
як так в першому завданні з дз з (n-1)*n
виходить факторіал?
дякую)
sasha   |2019-02-06 23:09:56
Навіщо взагалі створювати прототипи
функції, якщо їх можна оголосити в main?
І як
так в першому завданні з дз вийшов
факторіал з формули (n-1)*n?
Дякую
Залишити коментар
Ім`я:
e-mail:
 
Тема:
 
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch:
:(:shock::X:side::):P:unsure::woohoo::huh::whistle:;):s
:!::?::idea::arrow:
 
Введіть цей настирливий код
Русская редакция: www.freedom-ru.net & www.joobb.ru

3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved."

 

Підписка

Хто онлайн?

Немає
На даний момент 24 гостей на сайті

Український рейтинг
TOP.TOPUA.NET