Затем управление программой передается строке 13, принадлежащей функции main(), которая показывает, что переменные получили назад свои исходные значения и все изменения, произошедшие в функции, аннулированы!
Напомним, что в данном случае переменные передаются в функцию swap() как значения, т.е. в функции swap() были созданы копии этих значений, которые являются локальными по отношению к этой функции. Обмен значениями, выполненный в строках 23—25, был реализован на этих локальных переменных, но это никак не повлияло на переменные, оставшиеся в функции main().
На занятиях 8 и 10 вы узнаете альтернативные способы передачи параметров функциям, которые позволят изменять исходные переменные в функции main().
Подробнее о возвращаемых значениях
Функции возвращают либо реальное значение, либо значение типа void, которое служит сигналом для компилятора, что никакое значение возвращено не будет.
Чтобы обеспечить возврат значения из функции, напишите ключевое слово return, а за ним значение, которое должно быть возвращено. В качестве возврата можно задавать как константные значения, так и целые выражения, например:
return 5;
return (x > 5);
return (MyFunction());
Все приведенные выше выражения являются правомочными установками возврата функций, если исходить из того, что функция MyFunction() сама возвращает некоторое значение. Второе выражение, return (x > 5), будет возвращать false, если x не больше 5, или true, если x больше 5. Таким образом, если в возврате задается логическое выражение, то возвращаются не значения переменной x, а логические значения false или true (ложь или истина).
После того как в функции встретится ключевое слово return, будет выполнено выражение, стоящее за этим ключевым словом, и его результат будет возвращен в основную программу по месту вызова функции. После выполнения оператора return программа немедленно переходит к строке, следующей после вызова функции, и любые выражения, стоящие в теле функции после ключевого слова return, не выполняются.
Однако функция может содержать несколько операторов return. Эта идея иллюстрируется в листинге 5.6.
Листинг 5.6. Использование нескольких операторов return
1: // Листинг 5.6. Использование нескольких
2: // операторов return в теле Функции
3:
4: #include<iostream.h>
5:
6: int Doubler(int AmountToDouble);
7:
6: int main()
9: {
10:
11: int result = 0:
12: int input;
13:
14: cout << "Enter а number between 0 and 10,000 to double: ":
15: cin >> input;
16:
17: cout << "nBefore doubler is called... ";
18: cout << "ninput: " << input << M doubled: " << result << "n";
19:
20: result = Doubler(input);
21:
22: cout << "nBack from Doubler...n";
23: cout << "ninput: " << input << " doubled: " << result << "n";
24:
25:
26: return 0;
27: }
28:
29: int 0oubler(int original)
30: {
31: if (original <= 10000)
32: return original * 2;
33: else
34: return -1;
35: cout << "Vou can't get here!n";
36: }
Результат:
Enter a number between 0 and 10,000 to double: 9000
Before doubler is called...
input: 9000 doubled: 0
Back from doubler...
input: 9000 doubled: 18000
Enter a number between 0 and 10.000 to double: 11000
Before doubler is called...
input: 11000 doubled: 0
Back from doubler...
input: 11000 doubled: -1
Анализ: В строках 14 и 15 программа предлагает пользователю ввести число и coхраняет его в переменной input. В строке 18 отображается только что введенное число вместе со значением локальной переменной result. В строке 20 вызывается функция Doubler() и введенное значение передается ей как параметр. Результат выполнения функции присваивается локальной переменной result, и в строке 23 снова выводятся значения тех же переменных.
В строке 31, относящейся к функции Doubler(), значение переданного параметра сравнивается с числом 10 000. Если окажется, что оно не превышает 10 000, функция возвращает удвоенное значение исходного числа. Если оно больше 10 000, функция возвращает число -1 в качестве сообщения об ошибке.
Выражение в строке 35 никогда не будет достигнуто, потому что при любом значении переданного параметра (большем 10 000 или нет) возврат из функции будет осуществлен либо в строке 32, либо в строке 34, но в любом случае до строки 35. Хороший компилятор сгенерирует предупреждение, что это выражение не может быть выполнено, и хороший программист должен принять соответствующие меры!
Вопросы и ответы
В чем состоит разница между объявлениями int main() и void main() и какое из них лучше использовать? Ведь оба варианта работают одинаково хорошо, поэтому стоит ли применять первый вариант int main(){ return 0; }?
Оба объявления будут работать с большинством компиляторов, но только вариант int main() является ANSI-совместимым, следовательно, только объявление int main() гарантирует работу программы.
По существу, отличие состоит в следующем. При использовании объявления int функция main()возвращает значение для операционной системы. После завершения работы вашей программы это значение могут перехватить, например, программы пакетной обработки.
И хотя вы вряд ли будете использовать возвращаемое значение, стандарт ANSI требует его присутствия.
Значения параметров, используемые по умолчанию
Для каждого параметра, объявляемого в прототипе и определении функции, должно быть передано соответствующее значение в вызове функции. Передаваемое значение должно иметь объявленный тип. Следовательно, если некоторая функция объявлена как
long myFunction(int);
то она действительно должна принимать целочисленное значение. Если тип объявленного параметра не совпадет с типом передаваемого аргумента, компилятор сообщит об ошибке.
Из этого правила существует одно исключение, которое вступает в силу, если в прототипе функции для параметра объявляется стандартное значение. Это значение, которое используется в том случае, если при вызове функции для этого параметра не установлено никакого значения. Несколько изменим предыдущее объявление:
long myFunction (int x = 50);
Этот прототип нужно понимать следующим образом. Функция myFunction возвращает значение типа long и принимает параметр типа int. Но если при вызове этой функции аргумент предоставлен не будет, используйте вместо него число 50. А поскольку в прототипах функций имена параметров не обязательны, то последний вариант объявления можно переписать по-другому:
long myFunction (int = 50);
Определение функции не изменяется при объявлении значения параметра, задаваемого по умолчанию. Поэтому заголовок определения этой функции будет выглядеть по-прежнему:
long myFunction (int x)
Если при вызове этой функции аргумент не устанавливается, то компилятор присвоит переменной x значение 50. Имя параметра, для которого в прототипе устанавливается значение по умолчанию, может не совпадать с именем параметра, указываемого в заголовке функции: значение, заданное по умолчанию, присваивается по позиции, а не по имени.
Установку значений по умолчанию можно назначить любым или всем параметрам функции. Но одно ограничение все же действует: если какой-то параметр не имеет стандартного значения, то ни один из предыдущих по отношению к нему параметров также не может иметь стандартного значения. Предположим, прототип функции имеет вид
long myFunction (int Param1, int Param2, int Param3);
тогда параметру Param2 можно назначить стандартное значение только в том случае, если назначено стандартное значение и параметру Param3. Параметру Param1 можно назначить стандартное значение только в том случае, если назначены стандартные значения как параметру Param2, так и параметру Param3. Использование значений, задаваемых параметрам функций по умолчанию, показано в листинге 5.7.
Листинг 5.7. Использование значений, заданных по умолчанию для параметров функций
1: // Листинг 5.7. Использование стандартных
2: // значений параметров
3:
4: #include <iostream.h>
5:
6: int VolumeCube(int length, int width = 25, int height = 1);
7:
8: int main()
9: {
10: int length = 100;
11: int width = 50;
12: int height = 2;
13: int volume;
14:
15: volume = VolumeCube(length, width, height);
16: cout << "First volume equals: " << volume << "n";
17:
18: volume = VolumeCube(length, width);
19: cout << "Second time volume equals: " << volume << "n";
20:
21: volume = VolumeCube(length);
22: cout << "Third time volume equals: " << volume << "n";
23: return 0;
24: }
25:
26: VolumeCube(int length, int width, int height)
27: {
28:
29: return (length * width * height);
30: }
Результат:
First volume equals: 10000
Second time volume equals: 5000
Third time volume equals: 2500
Анализ: В прототипе функции VolumeCube() B строке 6 объявляется, что функция принимает три параметра, причем последние два имеют значения, устанавливаемые по умолчанию.