Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Otvety_ekzamen_CPP.doc
Скачиваний:
3
Добавлен:
21.09.2019
Размер:
311.81 Кб
Скачать

Билет №1.

Объявление функции. Определение функции. Вызов функции.

Функция представляет собой последовательность инструкций, предназначенных для решения определённой задачи.

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

спецификатор_типа имя_функции (список_параметров)

и описывает соответственно тип возвращаемого значения, имя функции и список параметров.

Тип возвращаемого функцией значения может быть типом статического массива или именем функции. Параметры в списке перечисляются через запятую.

Если функция не возвращает никакого значения, то предполагается, что она возвращает пустое значение. В этом случае для указания типа используется void.

Если вообще не указан тип возвращаемого значения, то по умолчанию возвращается значение типа int. Так не рекомендуется писать.

Если в объявлении функции указаны только типы параметров, то такое объявление функции называется прототипом функции.

int add (int, int);

Если функция не имеет списка параметров, то тогда нужно ставить ключевое слово void:

int print (void);

Если void не записано, то он подразумевается по умолчанию:

int print ();

void main () – ничего не возвращает и ничего не принимает.

В языке программирования допускается использование функций с переменным количеством параметров. В этом случае в списке параметров должен быть хотя бы 1 параметр, а затем ставится многоточие:

int add_num (int, …);

Переменная n содержит в себе количество параметров функции.

Определение функции

Имеет следующий вид:

спецификатор_типа имя_функции (спиок_параметров)

{

/*набор инструкций*/ - тело функции

}

Заголовок функции совпадает с её объявлением. Тело функции содержит определения и инструкции, которые выполняются при вызове функции. В отличие от объявления функции, которое может находиться в любом месте программы, определение функции должно находиться вне блока.

Для возврата значений из функции используется инструкция return:

return выражение;

После выполнения данной инструкции исполнение функции прекращается и функция возвращает значение, которое вычисляется в выражении.

Тип возвращаемого значения должен совпадать со спецификатором типа функции.

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

int add (int x, int y);

{return x + y; }

Если функция возвращает void, то инструкцию return можно не писать.

Параметры функции являются локальными переменными и к ним нельзя обратиться из других функций.

Замечание: в языке С и С++ содержатся библиотеки стандартных функций. Для того чтобы в программе можно было использовать эти библиотеки, нужно подключить специальные файлы, которые содержат прототипы этих стандартных функций. Эти файлы называются заголовочными файлами и имеют расширение h (stdio.h и т.д.). Для подключения используется директива процессора #include.

Вызов функции

Осуществляется всегда либо после объявления, либо после определения функции. Имеет вид:

имя_функции (список параметров)

и называется оператором вызова функции.

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

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

# include <stdio.h>

int add (int x, int y) {return x + y}

void main ()

{

int z;

z = add (1,2);

printf (“z = %d”, z);

printf (“1+2 = %d”, add (1,2));

int a = 1, b = 2;

z = add (a, b);

Замечание: поскольку параметры передаются по значению, что бы мы не делали с параметрами функции, испортить их нельзя.

int add (int x, int y)

{x = x + y;

return x;

}

int a = 1, b = 2;

z = add (a, b);

add (a, b) – вывод на печать.

Пример функции (написать любую).

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

Сигнатурой функции называется список типов её параметров.

Перегрузкой функции называется объявление в одной области видимости нескольких функций с одинаковым именем, но разными сигнатурами.

На перегрузку функций накладываются ограничения:

  1. нельзя перегружать функции, которые отличаются только возвращаемым значением, т.е. в этом случае компилятор не знает, какую из них использовать при вызове, если для возвращаемого значения требуется преобразование типов;

  2. типы параметров которых отличаются только тем, что переопределяются при помощи объявления typedef;

  3. типы параметров которых отличаются только тем, что один из них массив, а второй – указатель на тип, который соответствует типу элементов массива;

  4. параметры которых отличаются только значениями, заданными по умолчанию.

Например:

int neg (int n) {return n;}

float neg (float f) {return f;}

double neg (double d) {return d;}

void main ()

{float f = neg (5, 5f);

double d = neg (5, 5);

}

В случае вызова одной из перегружаемых функций компилятор выбирает нужную функцию по лучшему соответствию типов аргументов типам параметров. Выбор такой функции делится на 3 этапа:

1) строится множество функций-кандидатов, т.е. таких функций, имя которых совпадает с именем вызываемой функции;

2) из множества функций-кандидатов выбираются функции, у которых количество параметров равно количеству аргументов вызываемой функции;

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

Унарные операторы.

Префиксные унарные операторы могут быть перегружены как нестатические члены класса без параметров:

Возвращаемый_тип operator @ ();

Или как операторы, не являющиеся членами класса с одним параметром:

Возвращаемый_тип operator @ (параметр);

Символ @ обозначает один из следующих унарных операторов: & - + * ! ~.

Пример:

1 вариант – ratio operator – () {return ratio (-n.d);}

2 вариант – friend ratio operator – (const ratio &r);

ratio operator – (const ratio &r)

{

return ratio (-r.n, r.d)

}

Билет №2.

Указатели.

Указатель – переменная или именованная константа, которая содержит адрес другой переменной, именованной константы или функции. Для объявления указателя необходимо перед именем переменной, которая объявляется как указатель поставить символ *. В этом случае переменная является указателем на данные, тип которых задан спецификатором типа.

int*p; /*указатель на целое число*/

char*cp; /*указатель на символ*/

doudle*dp; /*указатель на число с плавающей точкой*/

Для задания указателей двух или более одного типа одним оператором необходимо перед каждым указателем обязательно ставить *.

int*p, р1;

*p – указатель на целочисленный тип.

р1 – переменная целого типа.

int*p, *р1; - обе переменные будут являться указателями.

Замечание: при задании одной переменной указателя записи int *p; и int* p; будут одинаковы.

При объявлении указателя его необходимо проинициализировать, т.е. поместить в него адрес переменной. Если размещение адреса на данный момент невозможно, то ему нужно присвоить значение символической константы NULL, которая содержит нулевой адрес:

int*p = NULL;

Присваивание такой константы упрощает процесс отладки программы.

  1. Преобразование типов указателей

В языке программирования С++ приведение типов указателей подчиняется правилам:

  1. указатель на любой тип данных может быть приведён к указателю на любой другой тип данных только явно:

int*p, *р1;

//были проинициализированы

р = р1;

р1 = р;

float *f, f = (float) p;

Оператор явного приведения.

  1. указатель типа void (указатель на неопределённый или пустой тип). Можно только явно привести к указателю на любой тип данных. Указатель на любой тип данных можно неявно привести к указателю void *p;

int *p // p = (int) p;

float *p // p = (float) p;

  1. Выравнивание адресов на границу слова (2 байта) или двойного слова (4 байта) не учитывается, поэтому операция преобразования типов указателей может дать неопределенный результат.

  2. указатель, значение которого равно NULL, преобразовывается на целое число, значение которого равно 0 и наоборот.

  1. Операторы определения адреса и обращения по адресу

Для получения адреса переменной или именованной константы используется оператор &, который называется оператором определения адреса и имеет следующий вид:

&операнд,

где операндом должно быть L-value, удовлетворяющее двум ограничениям:

  1. не указывает на битовое поле

  2. не имеет спецификатор класса памяти (регистр). Пример:

int n;

int*p;

p=&n;

получить значение переменной или именованной константы, адрес которой хранится в указателе, можно при помощи оператора обращения по адресу (*) или оператора разыменование, который имеет вид: *операнд, где операнд должен быть указателем. Пример:

int n=2, m;

int*p=&n;

m=*p; /*m=2*/

*p=5; /*n=5*/

если указатель содержит ошибочный адрес, то в этом случае может произойти как прерывание программы (access violation), так и нормальное завершение, но полученные данные будут ошибочны.

  1. Указатели на константы и константные указатели

При работе с указателями следует различать использование модификатора доступа const перед типом переменной, на которую ссылается указатель, и перед самим указателем. В первом случае указатель ссылается на типизированную константу, а во втором является константным указателем.

const int n = 5;

const int*p = NULL; //указатель на константу!

p = &n;

Константный указатель:

int n = 2;

int *const p = &n;

(*p)++; //n = 3

Значения константного указателя менять нельзя, т.е. нельзя писать р++ и нельзя:

int m = 5;

p = &m;

Константный указатель на константу:

const int n = 5;

const int *const p = &n;

Нельзя писать:

(*p)++; p++ //n изменять нельзя.

  1. Арифметические действия с указателями

Над указателями одного типа можно выполнить арифметическую операцию вычитания. Результатом этой операции будет целое число, которое указывает, насколько один адрес памяти смещён относительно другого в единицах, равных длине базового типа данных указателей.

int a [6];

int m, n;

n = &a [5] - &a [3]; //n = 2;

m = &a [3] - &a [5]; //m = -2;

К указателям можно прибавить или вычесть целое число. В этом случае значение указателя соответственно увеличится или уменьшится на это число, умноженное на длину базового типа данных указателя.

int a [5];

int *p = a+2; //*p = &a [2]

К указателю можно применять операции «++» и «--». В этом случае значение указателя соответственно увеличивается или уменьшается на длину базового типа данных указателя:

double *p; p++; ++p;

Ввод-вывод элементов массива осуществляется в цикле (чаще всего используют цикл for):

int a [5];

int i;

printf (“input five integers: ”);

for (i = 0; i<5; i++)

scanf (“%d”, &a [i]);

Можно записать иначе:

scanf (“%d”, a + i);

Для вывода такая последовательность:

printf (“the array:\n”);

for (i = 0; i<5; i++)

printf (“a [%d] = %d”, i, a [i]);

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]