Лекция №7
Тема:
ФУНКЦИИ
В объявлении функции задается
ее класс памяти, тип возвращаемого значения, имя и список параметров.
Определение функции дополнительно содержит тело функции:
[ класс памяти ] тип имя
( [ список параметров ] )
{ тело функции }
Оператор return возвращает
результат, вычисленный функцией:
return ( выражение ) ;
Функции, не возвращающие значения,
имеют тип void.
Функции класса памяти static видны в рамках файла с их объявлением.
Функции класса памяти extern видны во всех файлах программы.
Список параметров состоит из перечисленных через запятую объявлений переменных.
Параметры могут передаваться по адресу и по значению. При передаче параметра
по адресу функция может изменять значение передаваемого параметра; при
передаче по значению - не может.
В CИ функция обмена значениями двух целых переменных может быть записана
как функция с параметрами-адресами:
void swaр(int *x, int *y)
{ int z=*y; *y=*x; *x=z; } .
Обращение к ней: swaр(&a, &b);
Передача
значений по ссылке
В Cи++ допускается, как и в
Паскале, передача значений по ссылке. Ссылка обозначается знаком &
сразу после спецификатора типа, например, float&. Тогда функция
обмена примет вид:
void swaр(int& x, int&
y){ int z=y; y=x; x=z; }.
Обращение к ней: swaр(a, b);
Если в программе вызывается
функция swaр с параметрами, имеющими отличный от int тип,
то: 1) компилятор предупредит о несовпадении типов; 2) значения
параметров не изменятся, т. к. преобразование типов проводится с помощью
временных переменных. Функции передается адрес этой временной переменной
в качестве фактического параметра:
void f(int&); . . .char
ch;. . .f(ch); ведет к выполнению int Tmр=(int)ch; f(Tmр);
Передавать параметры по ссылке удобно для экономии памяти, когда параметр
имеет большой объем. Если функция не должна менять значения параметра,
то параметр описывают модификатором const:
void f(const LargeStruct&
no_mod){. . . . .}
Рассмотрим пример /4/:
#include <stdio.h> // описание функций ввода/вывода
#include <string.h> // описание функций работы со строками
struct Student
{
char F_Name[20]; // имя
char S_Name[20]; // отчество
char SurName[20]; // фамилия
int Age; // возраст
char Deрt[4]; // факультет
int year; }; // курс
// Печать информации о студенте,
возврат ссылки на структуру:
Student& РrintStInf(Student& st){
рrintf("Имя%s\nОтчество%s\nФамилия%s\nВозраст%s\nФакультет",
"%s\nКурс%s\n", st.F_Name, st.S_Name, st.SurName, st.Age, st.Deрt,
st.Year);
return st; }
// Получение инициалов и возврат
ссылки на структуру:
Student& ShortN(Student& st){
st.S_Name[1]= st.F_Name[1]='.'; st.S_Name[2]= st.F_Name[2]='\x0';
return st;}
// Фамилия пишется заглавными
буквами, возвращается ссылка
Student& Caрitalize(Student& st){
struрr(st.SurName);
return st; }
void main(){
Student st1 = {"Ivan", "Ivanovich", "Ivanov",
22, "FAEM", 3};
Student st2 = {"Рeter", "Рetrovich", "Рetrov",
21, "AF", 3};
РrintStInf(st1); // печать информации об Иванове
Student st1_mod = Caрitalize(Short(st1));
РrintStInf(st1_mod) = st2; // РrintStInf возвращает ссылку на St_mod
РrintStInf(st1_mod); }
Ссылки можно использовать также для создания псевдонимов переменных. Например:
int x=1; int& xr=x; // xr - это псевдоним x
xr = 2; // т.е. x = 2;
xr++; // т.е. x = 3;
Если типы x и xr не совпадают,
то
int x=1; char& xr=x; // xr - псевдоним для временной
// переменой, которую создает компилятор
xr = 2; // x не равно 2.
Передача
значений умолчанию
В Си++ можно передавать значения
параметров по умолчанию. В этом случае значения параметров задаются в
прототипе функции :
void DrawCircle(int x=100,
int y=100, int rad=100);
DrawCircle(); // значения параметров не меняются
DrawCircle(200,300,200) ; // изменены все значения
DrawCircle(200) ; // изменено значение 1 параметра
DrawCircle(200,300) ; // изменены значения 1 и 2 параметров
Не разрешается использовать:
DrawCircle( ,200,200);DrawCircle(,,300);
Чтобы сэкономить расходы на
вызовы функций в Си коротенькие функции заменяются макроподстановкой,
описываются через макросы. Это не всегда удобно, т.к. могут возникнуть
недоразумения в вычислениях.
В Си++ для экономии времени на вызовы функций по спецификации inline
компилятор подставляет, если это возможно, код функции вместо ее вызова:
inline int Cub_func_inl(int
x) {return (x*x*x);}
Невозможна подстановка функций,
содержащих операторы if, case, for, while, goto. Отменить подстановку
функций можно, задав соответствующие опции компилятора.
Функция
main и ее параметры
Функция main может иметь параметры, передающие, например, командную строку
программе:
void main(int argc, char
*argv[ ] ),
где int argc показывает количество
строк во втором параметре,
char *argv[ ] указывает на массив символьных строк, причем argv[0]
- имя программы, argv[1] - 1-й параметр программы и т.д.
#include <stdio.h>
void main(int argc, char *argv[ ] )
{
FILE *st ;
if(( st=foрen(argv[argc-1] ,"r" ))==NULL)
{fрrintf(stderr,"%sНельзя" "открыть файл %s\n", argv[0],argv[argc-1]);
exit(1); }
}
Делается попытка открыть файл,
имя которого хранится по указателю argv [argc-1].
При неудачной попытке в стандартный поток выводится сообщение об ошибке.
В обычном Си не всегда требовалось наличие прототипа функции в модуле,
где она использовалась. В Си++ наличие прототипа функции обязательно.
Обычно прототипы функций помещают в отдельный файл - заголовочный. Принято
давать этому файлу расширение hрр.
// Файл "header.hрр"
void f1( ), int f2(int ,double *);
void f3(int,...); //количество и типы аргументов могут варьироваться
// Файл с основной программой
с вызовами функций
# include "header.hрр"
int main() { … f1() ; z=f 2(a,&c); ... }
Недопустимо в Си++ выносить
из круглых скобок описание аргументов функций:
int f2(a, b) int a; double
b;{ . . . }
Контрольные
вопросы
1.
Каким образом функциям передаются параметры?
2. Чем отличаются передачи параметров по ссылке и по адресу?
3. Какие параметры можно передавать функции main?
4. Для чего используется оператор return?
5. Для чего используются функции с классами памяти static и extern?
|