§14 Функции возвращающие значение

Функции возвращающие значение

Функции возвращающие значение имеют тип, который соответствует типу возвращаемого значения. Эти функции возвращают значение в точку возврата операцией обращения. Соответственно функция должна выступать как операнд в выражениях с присваиванием или выводом. Это отличает синтаксис функций возвращающих и не возвращающих значение. В определении функции должна быть инструкция return, которая принимает выражение для определения возвращаемого значения. Ниже приводится схема размещения в программе функции возвращающей значение.

Функция в программе

Объявление функции. Прототип

Тип_возвращаемого_значения Имя_функции(список типов_параметров);

Вызов функции

int main() {
    // Операция вызова в выражении с присваиванием:
    Var = Имя_функции(список аргументов);
    // Операция вызова в потоке вывода:
    cout << Имя_функции(список аргументов);
}

Определение функции

Тип_возвращаемого_значения Имя_функции(список параметров) {
    // Инструкции
    return Выражение_возвращающее значение;
}

Инструкция return

Инструкция return завершает выполнение функции и возвращает её значение. Инструкция return возвращает только одно значение (переменной или выражения). В некоторых случаях оператор return может применяться и в функциях не возвращающих значение (программа 13.1 стр. 23). Но в этих функциях пустая инструкция return применяется для выхода из функции и возврата управления в вызывающую программу.
Приведем пример программы с функцией возвращающей значение.
Составим программу с функцией возвращающей случайное значение на отрезке [a, b]. Назовем ее myRand(). Эта функция двух аргументов может применяться, например, для заполнения массива.
Программа 14.1

#include <iostream>
#include <ctime>
#include <random>
using namespace std;

int myRand(int, int);

int main() {
	int a, b, r, n;
	// Границы отрезка:
	cout << "a = "; cin >> a;
	cout << "b = "; cin >> b;
	// Сколько случайных чисел нужно выводить?
	cout << "n = "; cin >> n;
	for (int i = 1; i <= n; i++) {
		r = myRand(a, b);
		cout << r << endl;
	}
	return 0;
}

int myRand(int x, int y) {
    static default_random_engine rnd(time(0));
    static uniform_int_distribution<unsigned> d(x, y);
	return d(rnd);
}
a = 7
b = 23
n = 4
7
13
12
20

В теле функции может быть несколько инструкций return. В таком случае только одна инструкция return вернет значение. Это можно запрограммировать с помощью условной инструкции. Приведем пример такой программы. Дано двузначное целое число n. Если это число четное получить произведение его цифр, иначе получить сумму его цифр.
Программа 14.2

#include <iostream>
using namespace std;

int resPow(int);

int main() {
	int n;
	cout << "n = "; cin >> n;
	cout << resPow(n) << endl;
	return 0;
}

int resPow(int m) {
	if (m % 2 == 0)
		return (m % 10) * (m / 10);
	else
		return m % 10 + m / 10;
}

Данную функцию можно было определить и более лаконично, если вместо условной инструкции применить тернарную операцию:

int resPow(int m) {
	return !(m % 2) ? (m % 10) * (m / 10) : m % 10 + m / 10;
}

Использование тернарной операции в сочетании с инструкцией return находит довольно частое применение.
Если требуется возвращать функцией более одного значения, то необходимо прибегать к передаче параметров по ссылке или указателю. Рассмотрим пример. Разработать программу в которой используется функция возвращающая разряды двузначного числа.
Программа 14.3

#include <iostream>
using namespace std;

int razr(int&, int&);

int main() {
	int a, b;
	cout << "Введите число: "; cin >> a;
	a = razr(a, b);
	cout << "Десятки: " << a << endl
		 << "Единицы: " << b << endl;
	return 0;
}

int razr(int &x, int &y){
	y = x % 10;
	return x / 10;
}
Введите число: 13
Десятки: 1
Единицы: 3

Перегрузка функций

Перегрузка функций позволяет использовать несколько функций с одним и тем же именем, но различными параметрами. Каждая такая функция должна иметь свой прототип и свое определение. Вызов той или иной перегруженной функции будет определять набор аргументов (сигнатура). Сигнатуры перегруженных функций должны различаться либо по типу, либо по количеству, либо и по тому, и по другому. Рассмотрим простой пример. Требуется составить программу которая выводит половину произведения аргументов, если в сигнатуре два аргумента и среднее арифметическое аргументов, если в сигнатуре три аргумента.
Программа 14.4

#include <iostream>
using namespace std;

double avr(double, double);
double avr(double, double, double);

int main() {
    double x, y, z;
    cin >> x >> y >> z;
    cout << avr(x, y)    << endl
         << avr(x, y, z) << endl;
	return 0;
}

double avr(double p, double n) {
    return p * n / 2;
}

double avr(double p, double n, double m) {
	return (p + n + m) / 3;
}
1.2 5.3 7.8
3.18
4.76667

Перегрузка функций, так называемый полиморфизм функций, применяется в том случае, если в большой программе существует набор некоторых функций, которые решают однотипные задачи (один класс задач), но реализация каждой из них требует некоторых изменений (например, использование иных типов данных или иного представления результата). Это позволяет разработчику сократить количество используемых имен функций в своей программе.
Заметим так же, что перегруженные функции могут возвращать разный тип данных, при условии, что сигнатуры этих функций будут различаться.

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

Шаблоны функций (function template) предоставляют инструменты для проектирования функции. Шаблон позволяет отвлечься от конкретного типа данных, с которыми функция будет работать. Шаблон - является руководством для создания реального объекта. Это значит, что шаблон не создает функцию, а указывает компилятору как создать определение функции для соответствующего типа данных, который будут иметь, в определенный момент работы программы, аргументы создаваемой функции. Шаблоны применяются в тех случаях, когда для разных типов данных должен использоваться один и тот же алгоритм.
Определение шаблона:

template <typename T1, typename T2, ...>
Определение функции

где T1, T2 - произвольные имена параметров типа шаблона. Каждому параметру типа должно предшествовать ключевое слово typename. Эти параметры применяются для указания типов различных объектов в заголовке и в теле функции. Компилятор свяжет эти параметры с соответствующим типом аргументов для определения типа параметров функции.
Приведем пример задачи. Составить программу в которой необходимо сравнивать два объекта одного типа. Продемонстрировать использование созданной шаблонной функции для сравнения объектов разного типа.
Программа 14.5

#include <iostream>
using namespace std;

template <typename T>
bool comp(T, T);

int main() {
    int x1 = 10, x2 = 5;
    char c1 = 'a', c2 = 'z';
    string s1("sun"), s2("moon");
    cout << boolalpha << comp(x1, x2) << endl
         << boolalpha << comp(c1, c2) << endl
         << boolalpha << comp(s1, s2) << endl;
    return 0;
}

template <typename T>
bool comp(T a, T b) {
    return (a > b);
}
true
false
true

Шаблоны в C++ являются основой для обобщенного программирования, целью которого является возможность написания алгоритмов очень высокого уровня абстракции. Шаблоны широко применяются в стандартной библиотеке C++. Большой вклад в появление развитых средств обобщённого программирования в C++ внёс Александр Степанов - русско-американский учёный в области информатики и вычислительной техники. В 1995 г. А. Степанов получил премию Dr.Dobb’s Excellence In Programming Award за создание STL, которую разделил с Линусом Торвальдсом.

Вопросы
  1. В чем различие функции возвращающей и не возвращающей значение?
  2. Когда перегрузка функций будет полезна, а в каких случаях её нужно избегать?
  3. Когда применяется шаблон функции?
  4. В каких случаях в одной функции применяется две инструкции return?
  5. В каких случаях функцию можно использовать как "логическую"?
Домашняя работа
  1. Составьте функцию, определяющую сумму цифр введенного целого числа.
  2. Напишите программу в которой используется перегруженная функция разворачивающая числа и слова задом-наперед. Например, 7890 -> 0987, qwerty -> ytrewq.
Учебник

§60

Литература
  1. Прата, Стивен. Язык программирования C++. Лекции и упражнения, 6-е изд.: Пер. с англ. — М.: ООО «И.Д. Вильяме», 2012
  2. Липпман Б. Стенли, Жози Лажойе, Барбара Э. Му. Язык программирования С++. Базовый курс. Изд. 5-е. М: ООО "И. Д. Вильямс", 2014
  3. Эллайн А. C++. От ламера до программера. СПб.: Питер, 2015
  4. Джосаттис Н. М. Стандартная библиотека C++: справочное руководство, 2-е изд.-М.: Вильямс, 2014


Print Friendly, PDF & Email

Добавить комментарий