Функции в C++
При написании программы часто требуется выполнить одинаковую последовательность операций для получения какого-либо результата. К примеру, предположим, что необходимо получить процентное отношения для двух исходных чисел:
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
int a = 1;
int b = 10;
double result1 = 100.0 * a / b;
cout << result1 << '\n';
int c = 2;
int d = 30;
double result2 = 100.0 * c / d;
cout << result2 << '\n';
}
В обоих случая повторяется одна и та же последовательность, что в этом случае, вообщем-то не мешает, но может сильно навредить, если такие части будут повторяться в различных участках проекта. Удобней вынести этот общий блок операций, дать ему какое-то имя и вызывать по мере необходимости. Функция в программе, так же как и функция в её математическом смысле, имеет аргументы и возвращаемое значение. Совокупность имени функции, её аргументов и возвращаемого значения называется сигнатурой метода (или функции).
В C++ как и во многих других языках программирования функции нельзя описать внутри другой функции, а требуется описать её отдельно. Таким образом, пример, описанный выше можно описать так:
#include <iostream>
using namespace std;
double percentage(int a, int b) {
return 100.0 * a / b;
}
int main(int argc, char *argv[]) {
double result1 = percentage(1, 10);
cout << result1 << '\n';
double result2 = percentage(2, 30);
cout << result2 << '\n';
}
Несколько функций можно группировать в области видимости. Возможность объединить несколько функций в рамках некоторого именованного пространства позволяет избежать коллизий имён с аналогичными функциями из других подключаемых библиотек, да и просто логически организовать ваш код. Слегка изменим код выше, введя в него две новых функций и разделяя его в разные логические структуры:
#include <iostream>
using namespace std;
namespace Math {
double percentage(int a, int b) {
return 100.0 * a / b;
}
double sum(int a, int b) {
return a + b;
}
}
namespace IO {
void printLine(double result) {
cout << result << '\n';
}
}
int main(int argc, char *argv[]) {
double result1 = Math::percentage(1, 10);
IO::printLine(result1);
double result2 = Math::percentage(2, 30);
IO::printLine(result2);
}
Кстати, ключевое слова using namespace std; позволяет для метода (функции) cout писать без указания именованного пространства, к которому оно относится.
Функции и её аргументы
Передача аргументов в функции может быть по значению или по ссылке. В первом случае, значение которое используется в функции является копией значения, которое передаётся в функцию. Во втором передаётся само значения без его копирования.
#include <iostream>
using namespace std;
void byValue(int a) {
a = 2;
}
void byReference(int& a) {
a = 2;
}
int main(int argc, char *argv[]) {
int value = 6;
byValue(value);
cout << "By value:\t\t" << value << '\n';
byReference(value);
cout << "By reference:\t" << value << '\n';
}
Ввывод в консоли:
By value: 6 By reference: 2
После вызова метода, который передаёт аргумент по ссылке, значение переменной value изменяется. Таким образом, с одной стороны имеется возможность не копировать значение (а процесс копирования может быть весьма затратен), но с другой стороны не гарантируется никаким образом неизменяемость значения переменной. Для того, чтобы гарантировать в коде, что переданное значение не будет изменено внутри метода к аргументу добавляют модификатор const:
void byReference(const int& a) {
a = 2;
}
При компиляции проекта будет выведена следующая ошибка:
Untitled.cpp:10:4: error: read-only variable is not assignable
a = 2;
~ ^
1 error generated.