Перейти к содержанию
Educora
Средний18 мин4 / 10

Функции

Пиши собственные функции: возвращаемые значения, параметры, прототипы, перегрузка, аргументы по умолчанию, передача по значению и по ссылке.

Проверь себя
В этом уроке ты узнаешь
  • Писать функцию с типом результата, параметрами и return и вызывать её
  • Перегружать функции и использовать аргументы по умолчанию
  • Объяснять разницу между передачей по значению и по ссылке
  • Передавать большие объекты по const-ссылке

Представь, что в игре ты в десяти местах считаешь расстояние между двумя персонажами и каждый раз копируешь одни и те же три строки. Найдёшь ошибку в формуле — придётся исправлять её в десяти местах! Эту проблему решают функции: код пишется один раз, получает имя и вызывается столько раз, сколько нужно. Одну функцию ты уже знаешь — это main.

Определение и вызов функции

Определение функции в C++ состоит из четырёх частей: тип возвращаемого значения, имя, параметры в скобках и тело в фигурных скобках. return возвращает результат в место вызова. У функции, которая ничего не возвращает, тип void.

C++
#include <iostream>
#include <string>

int square(int x) {
    return x * x;
}

void greet(std::string name) {
    std::cout << "Hello, " << name << "!\n";
}

int main() {
    greet("Leyla");
    int s = square(7);
    std::cout << "7 squared is " << s << '\n';
    std::cout << square(3) + square(4) << '\n';
    return 0;
}
Ожидаемый результат
Hello, Leyla!
7 squared is 49
25
Определение
Параметр и аргумент

Параметр — переменная, указанная в определении функции (int x). Аргумент — конкретное значение, которое передаётся ей при вызове (7 в вызове square(7)).

Компилятор читает файл сверху вниз, поэтому функцию нужно хотя бы объявить до её вызова. Если хочешь написать функцию после main, укажи вверху её прототип — заголовок без тела:

C++
#include <iostream>

int cube(int x);   // declaration (prototype)

int main() {
    std::cout << cube(3) << '\n';
    return 0;
}

int cube(int x) {  // definition
    return x * x * x;
}
Ожидаемый результат
27

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

В C++ может быть несколько функций с одинаковым именем, если у них различается количество или типы параметров. Это называется перегрузкой. Компилятор сам выбирает подходящий вариант по аргументам вызова. Выражение a > b ? a : b в примере — тернарный оператор: «если условие истинно, то a, иначе b».

C++
#include <iostream>

int maxOf(int a, int b) {
    return a > b ? a : b;
}

double maxOf(double a, double b) {
    return a > b ? a : b;
}

int maxOf(int a, int b, int c) {
    return maxOf(maxOf(a, b), c);
}

int main() {
    std::cout << maxOf(3, 8) << '\n';
    std::cout << maxOf(2.5, 1.5) << '\n';
    std::cout << maxOf(4, 9, 6) << '\n';
    return 0;
}
Ожидаемый результат
8
2.5
9

Аргументы по умолчанию

Параметру можно задать значение по умолчанию: если аргумент при вызове не указан, берётся оно. Правило такое: параметры со значениями по умолчанию должны стоять в конце списка.

C++
#include <iostream>
#include <string>

void printPrice(std::string item, int price, std::string currency = "AZN") {
    std::cout << item << ": " << price << ' ' << currency << '\n';
}

int main() {
    printPrice("Book", 12);
    printPrice("Headphones", 40, "USD");
    return 0;
}
Ожидаемый результат
Book: 12 AZN
Headphones: 40 USD

Передача по значению и по ссылке

По умолчанию C++ передаёт копию аргумента: даже если функция изменит параметр, переменная у вызывающей стороны останется прежней. Если после типа параметра написать &, параметр станет ссылкой — другим именем исходной переменной. Тогда изменения внутри функции коснутся и оригинала.

C++
#include <iostream>

void addBonusCopy(int points) {
    points += 10;
}

void addBonus(int& points) {
    points += 10;
}

int main() {
    int score = 50;
    addBonusCopy(score);
    std::cout << "After copy: " << score << '\n';
    addBonus(score);
    std::cout << "After reference: " << score << '\n';
    return 0;
}
Ожидаемый результат
After copy: 50
After reference: 60

Ссылки особенно полезны в двух случаях: когда функция должна изменить несколько переменных (например, поменять два значения местами) и когда ей нужно прочитать большой объект без копирования. Во втором случае пишут const std::string&: копия не создаётся, а функция не может изменить текст.

C++
#include <iostream>
#include <string>

void swapValues(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

void printBanner(const std::string& text) {
    std::cout << "*** " << text << " ***\n";
}

int main() {
    int x = 3;
    int y = 8;
    swapValues(x, y);
    std::cout << "x = " << x << ", y = " << y << '\n';
    printBanner("Game over");
    return 0;
}
Ожидаемый результат
x = 8, y = 3
*** Game over ***
СпособЗаписьМеняется ли оригинал?Когда использовать
по значениюint xнетмаленькие типы: int, double, char
по ссылкеint& xдафункция должна изменить переменную
по const-ссылкеconst std::string& sнетбольшие объекты, которые только читаются

Главное

  • Функция определяется как тип имя(параметры) { ... }; void ничего не возвращает.
  • Функцию нужно объявить до вызова — при необходимости напиши прототип.
  • Перегрузка — функции с одинаковым именем, но разными параметрами; нужный вариант выбирает компилятор.
  • Параметры со значениями по умолчанию стоят в конце списка.
  • Передача по значению создаёт копию, & работает с оригиналом, а const & позволяет безопасно читать без копирования.

Проверь себя

Вопросов: 10. Каждый правильный ответ приносит XP.

1 / 10
Какой тип у функции, которая ничего не возвращает?