Избегайте таких конструкций; если вам нужен локальный класс, значит, ваша функция слишком велика.
• Функции в других функциях: локальные функции (или вложенные функции).
void f
{
void g //
незаконно
{
// ...
}
// ...
}
В языке С++ это не допускается; не поступайте так. Компилятор выдаст ошибку.
• Блоки в функциях и других блоках: вложенные блоки.
void f(int x, int y)
{
if (x>y) {
// ...
}
else {
// ...
{
// ...
}
// ...
}
}
Вложенные блоки неизбежны, но они свидетельствуют о завышенной сложности программы и уязвимы для ошибок.
В языке C++ существует еще одно средство —
namespace
, которое используется исключительно для разграничения областей видимости (раздел 8.7).
Следите за выравниванием фигурных скобок, обозначающих вложение. Если бы выравнивания не было, код было бы невозможно читать. Рассмотрим пример.
// опасно уродливый код
struct X {
void f(int x) {
struct Y {
int f { return 1; } int m; };
int m;
m=x; Y m2;
return f(m2.f); }
int m; void g(int m) {
if (m) f(m+2); else {
g(m+2); }}
X { } void m3 {
}
void main {
X a; a.f(2);}
};
Неудобочитаемый код обычно скрывает ошибки. Если вы используете интегрированные среды разработки программ, то они автоматически выравнивают фигурные скобки (в соответствии со своими установками). Кроме того, существуют “программы изящного форматирования”, которые переформатируют исходный код в файле (часто предлагая пользователю выбор). Однако окончательная ответственность за удобочитаемость кода лежит на его авторе.
8.5. Вызов функции и возврат значения
Функции позволяют нам выражать действия и вычисления. Если мы хотим сделать что-то, заслуживающее названия, то пишем функцию. В языке С++ есть операторы (такие как
+
и
*
), с помощью которых можно вычислить новые значения по операндам, входящим в выражение, и инструкции (такие как
for
и
if
), позволяющие управлять порядком вычислений. Для того чтобы организовать код из этих примитивов, у нас есть функции.
Для выполнения своего предназначения функции принимают аргументы и, как правило, возвращают результат. В этом разделе мы рассмотрим механизмы передачи аргументов.
8.5.1. Объявление аргументов и тип возвращаемого значения
Функции в языке С++ используются для названия и представления вычислений и действий. Объявление функции состоит из типа возвращаемого значения, за которым следует имя функции и список формальных аргументов. Рассмотрим пример.
double fct(int a, double d); // объявление функции fct (без тела)
double fct(int a, double d) { return a*d; } // объявление функции fct
Определение состоит из тела функции (инструкций, выполняемых при ее вызове), в то время как объявление, не являющееся определением, просто завершается точкой с запятой. Формальные аргументы часто называют параметрами (parameters). Если не хотите, чтобы функция имела аргументы, не указывайте параметры. Например:
int current_power; // функция current_power не имеет аргументов
Если хотите, чтобы функция не возвращала никаких значений, укажите вместо типа возвращаемого значения ключевое слово
void
. Например:
void increase_power(int level); // функция increase_power
// ничего не возвращает
Здесь ключевое слово
void
означает “ничего не возвращает”. Параметры можно как именовать, так и не именовать. Главное, чтобы объявления и определения были согласованы друг с другом. Рассмотрим пример.
// поиск строки s в векторе vs;
// vs[hint] может быть подходящим местом для начала поиска
// возвращает индекс найденного совпадения; –1 означает "не найдена"
int my_find(vector<string> vs, string s, int hint); // именованные
// аргументы
int my_find(vector<string>, string, int); // неименованные аргументы
В объявлениях имена формальных аргументов не обязательны, просто они очень полезны для создания хороших комментариев. С точки зрения компилятора второе объявление функции
my_find
так же правильно, как и первое: оно содержит всю информацию, необходимую для ее вызова.