Справочник по C/C++
Функции

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

Основная форма записи функции имеет следующий вид

тип_возврата имя_функции(список_параметров)
{
	тело_функции
}
Тип данных, возвращаемых функцией, задаётся с помощью элемента тип_возврата. Под элементом список_параметров подразумевается список разделяемых запятыми переменных которые могут принимать любые аргументы, передаваемой функцией.

В версии C89, если тип данных возвращаемый функцией, явно не задан, то подразумевается тип int. В языке C++ и версии C99, тип int по умолчанию, не поддерживается, хотя в большинстве компиляторов C++ такое предположение остаётся в силе.

Прототипы функций

В языке C++ все функции должны иметь прототипы, а в языке C прототипы формально необязательны, но весьма желательны. Общая форма определения прототипа имеет следующий вид.

тип_возврата имя_функции(список_параметров);
Например.
float fn(float x);
//или
float fn(float);

В языке C для задания прототипа функции, не имеющей параметров, вместо списка параметров используется ключевое слово void. В языке C++ пустой список параметров в прототипе функция означает, что функция на имеет параметров. Слово void в этом случае необязательно.

Возврат значений (оператор return)

Возврат значений в функции осуществляется с помощью оператора return. он имеет две формы записи.

return;
return значение;

В языке C99 и C++ форма оператора return, которая не задаёт возвращаемого значения, должна использоваться только в void-функциях.

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

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

void func (int a){
	cout << "a=" << a << endl;
}
void func (int a, int b){
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;
}
void func(int a, double b){
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;
}
//вызываем
func (10);	//вызов func (int)
func (12, 24);	//вызов func (int, int)
func (99, 123.23);	//вызов func (int, double)

В каждом случае для определения того, какая версия функции func() будет вызвана, анализируется тип и количество аргументов.

Передача аргументов функции по умолчанию

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

void func (int a = 0, int b = 10){}
//вызов
func();
func(-1);
func(-1, 99);

Области видимости и время жизни переменных.

В языках C и C++ определенны правила видимости, которые устанавливают такие понятия как область видимости и время жизни объектов. Различают глобальную область видимости и локальную.

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

Локальная область видимости определяется границами блока. Имя объявленное внутри локальной области,известно только внутри этой области. Локальные переменные создаются при входе в блок и разрушаются при выходе из него. Это означает, что локальные переменные не хранят своих значений между вызовами функций. Чтобы сохранить значения переменных между вызовами, можно использовать модификатор static.

Рекурсия

В языках C и C++ функции могут вызывать сами себя. Этот процесс называют рекурсией, а функцию, которая сама себя вызывает — рекурсивной. В качестве примера приведём функцию fact(), вычисляющую факториал целого числа.

int fact (int n)
{
	int ans;
	if (n == 1) return 1;
	ans = fact (n-1) * n;
	return ans;
}

Функция main()

Выполнение C/C++ программы начинается с выполнения функции main(). (Windows-программы вызывают функцию WinMain() );

Функция main() не имеет прототипа. Следовательно, можно использовать различные формы функции main(). Как для языка C, так и для языка C++ допустимы следующие варианты функции main().

int main();
int main(int argc, char *argv[])

Как видно из второй формы записи, ф. main() поддерживает по крайней мере два параметра. Они называются argc и argv. Эти аргументы будут хранить количество аргументов командной строки и указатель на них соответственно. Параметр argc имеет целый тип, и его значение всегда будет не меньше числа 1, поскольку как предусмотрено в языках C и C++, первым аргументом является всегда имя программы. Параметр argv должен быть объявлен как массив символьных указателей, в которых каждый элемент указывает на аргумент командной строки. Ниже приведён пример программы, в которой демонстрируется использование этих аргументов.

#include <iostream.h>
using namespace std;
int main (int argc, char *argv[])
{
	if (argc < 2)
	cout << "Введите своё имя.\n";
	else
	cout << "привет " << argv[1];
	return 0;
}

Передача указателей

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

void swap (int *x, int *y)
{
	int temp;
	temp = *x;
	*x = *y;
	*y = temp;
}
//вызов
swap (&a, &b);

В языке C++ адрес переменной можно передать функции автоматически. Это реализуется с помощью параметра-ссылки. При использовании параметра-ссылки функции передаётся адрес аргумента, и функция работает с аргументом, а не с копией. Чтобы создать параметр-ссылку необходимо перед его именем поставить символ "амперсанда" (&). Внутри ф. этот параметр можно использовать обычным образом, не прибегая к оператору "звёздочка" (*), например.

void swap (int &x, int &y){
	int temp;
	temp = x;
	x = y;
	y = temp;
}
//вызов
swap (a, b);

Спецификаторы функций

В языке C++ определенны три спецификатора функций:

  • inline
  • virtual
  • explict

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

В качестве виртуальной функции (с помощью спецификатора virual) ф. определяется в базовом классе и переопределяется в производным классом. На примере виртуальных функций можно понять, как язык C++ поддерживает полиморфизм.

Спецификатор explicit применяется только к конструкторам, Конструктор, определённый как explicit, будет задействован только в том случае, когда инициализация в точности соответствует тому, что задано конструктором. Никаких преобразований выполняться не будет (т.е. спецификатор explicit создаёт "неконвертирующий конструктор").

Шаблоны функций

Общая форма определения шаблонной функции имеет следующий вид.

tetemplate тип> тип_возврата имя_функции (список_параметров)
{
	//тело функции
}
Здесь тип означает метку - заполнитель для типа данных, с которыми эта функция фактически будет иметь дело. В операторе template можно определить несколько параметров-типов данных, используя форму списка элементов, разделённых запятыми.

Рассмотрим пример.

template <class X> void swap (X &a, X &b)
{
	X temp;
	temp = a;
	a = b;
	b = temp;
}
//вызов
int a, b;
float x, y;
swap (a, b);
swap (x, y);

Указатели на функцию

На функцию, как и на любой другой объект языка C, Можно создать указатель. Синтаксис следующий.

тип_возврата (*имя_указателя)(описание_переменных);
Данное объявление создаёт указатель на функцию с именем имя_указателя, в которой содержаться переменные описание_переменных и которая возвращает значение типа тип_возврата.

Функцию с помощью указателя можно вызвать следующим образом.

имя_указателя = имя_функции;
переменная = имя_указателя (переменные);
Здесь первая строка создаёт ссылку на функцию имя_функции. Вторая строка собственно производит вызов функции через указатель имя_указателя, в которую передаются переменные переменные, возврат значения происходит в переменную переменная.

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

double y;
double (*p)(doublr x);
p=sin;			//создание указателя на функцию sin()
y = (*p)(2.5);	//вызов
y = p(2.5);		//вызов

//передача функции как параметра
double y;
double f(double (*c)(double x), double y){
	return c(y);	//вызываем переданную функцию в указатель c и возвращаем значение
}
y = f(sin, 2.5);	//передаём функции f функцию sin, а также параметр который будет обрабатываться

Создавать массивы указателей на функции так же можно.

int f1(void);
int f2(void);
int f3(void);
int (*p)(void) = {f1, f2, f3}

y = (*p[1])();	//вызов функции f2
y = p[2]();		//вызов функции f3


Смотрите также






Нет комментариев.



Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: