В определении функции может содержаться начальное (умалчиваемое) значение параметра. Это значение используется, если при вызове функции соответствующий параметр опущен. Все параметры, описанные справа от такого параметра, также должны быть умалчиваемыми.
const int N=20;//количество элементов массива
char mas1[N][10];//массив имен
int mas2[N]//массив возрастов
void init(int i, char* name=”Вася ”, int age=17)
{
strcpy(mas1[i],name);
mas2[i]=age;
}
Примеры использования функции init():
1. for (int i=1;i
init(i) ;
Всем элементам массива mas1 присваивается значение «Вася», всем элементам массива mas2 присваивается значение 17.
2. for (int i=1;i
{
char Name[10];
coutName;
init(I,Name) ;
}
Всем элементам массива mas1 присваивается значение переменной Name, всем элементам массива mas2 присваивается значение 17.
Функции с переменным числом параметров
В С++ допустимы функции, у которых при компиляции не фиксируется число параметров, и, кроме того, может быть неизвестен тип этих параметров. Количество и тип параметров становится известным только в момент вызова, когда явно задан список фактических параметров. Каждая функция с переменным числом параметров должна иметь хотя бы один обязательный параметр. Определение функции с переменным числом параметров:
тип имя (явные параметры,. . . )
{
тело функции
}
После списка обязательных параметров ставится запятая, а затем многоточие, которое показывает, что дальнейший контроль соответствия количества и типов параметров при обработке вызова функции производить не нужно. При обращении к функции все параметры и обязательные, и необязательные будут размещаться в памяти друг за другом. Следовательно, определив адрес обязательного параметра как p=k, где p — указатель, а k – обязательный параметр, можно получить адреса и всех остальных параметров: оператор k++; выполняет переход к следующему параметру списка. Еще одна сложность заключается в определении конца списка параметров, поэтому каждая функция с переменным числом параметров должна иметь механизм определения количества и типов параметров. Существует два подхода:
1) известно количество параметров, которое передается как обязательный параметр;
2) известен признак конца списка параметров.
//Найти среднее арифметическое последовательности
//чисел, если известно количество чисел
#include
float sum(int k, . . .)
//явный параметр k задает количество чисел
{
int *p=k;//настроили указатель на параметр k
int s=0;
for(;k!=0;k—)
s+=*(++p);
return s/k;
}
void main()
{
//среднее арифметическое 4+6
cout
//среднее арифметическое 1+2+3+4
cout
}
Для доступа к списку параметров используется указатель *p типа int. Он устанавливается на начало списка параметров в памяти, а затем перемещается по адресам фактических параметров (++p).
/*Найти среднее арифметическое последовательности чисел, если известен признак конца списка параметров */
#include
int sum(int k, …)
{
int *p = k; //настроили указатель на параметр k
int s = *p; //значение первого параметра присвоили s
for(int i=1;p!=0;i++) //пока нет конца списка
s += *(++p);
return s/(i-1);
}
void main()
{
//находит среднее арифметическое 4+6
cout
//находит среднее арифметическое 1+2+3+4
cout
}
Перегрузка функций
Цель перегрузки состоит в том, чтобы функция с одним именем по-разному выполнялась и возвращала разные значения при обращении к ней с различными типами и различным числом фактических параметров. Для обеспечения перегрузки необходимо для каждой перегруженной функции определить возвращаемые значения и передаваемые параметры так, чтобы каждая перегруженная функция отличалась от другой функции с тем же именем. Компилятор определяет, какую функцию выбрать по типу фактических параметров.
#include
#include
//сравнение двух целых чисел
int max(int a, int b)
{
if (ab) return a;
else return b;
}
//сравнение двух вещественных чисел
float max(float a, float b)
{
if(ab)return a;
else return b;
}
//сравнение двух строк
char* max(char* a, char* b)
{
if (strcmp(a,b)0) return a;
else return b;
}
void main()
{
int a1,b1;
float a2, b2;
char s1[20];
char s2[20];
cout
couta1;
coutb1;
cout
cout
couta2;
coutb2;
cout
cout
couts1;
couts2;
cout
}
Правила описания перегруженных функций:
- Перегруженные функции должны находиться в одной области видимости.
- Перегруженные функции могут иметь параметры по умолчанию, при этом значения одного и того же параметра в разных функциях должны совпадать. В разных вариантах перегруженных функций может быть разное количество умалчиваемых параметров.
- Функции не могут быть перегружены, если описание их параметров отличается только модификатором const или наличием ссылки: функции int f1(int, const int){…} и int f1(int, int){…} – не являются перегруженными, т. к. компилятор не сможет узнать какая из функций вызывается, потому что нет синтаксических отличий между вызовом функции, которая передает параметр по значению и функции, которая передает параметр по ссылке.
Шаблоны функций
Шаблоны вводятся для того, чтобы автоматизировать создание функций, обрабатывающих разнотипные данные. Например, алгоритм сортировки можно использовать для массивов различных типов. При перегрузке функции для каждого используемого типа определяется своя функция. Шаблон функции определяется один раз, но определение параметризируется, т. е. тип данных передается как параметр шаблона.
template
заголовок_функции
{
тело функции
}
Таким образом, шаблон семейства функций состоит из 2 частей – заголовка шаблона: template и обыкновенного определения функции, в котором вместо типа возвращаемого значения и/или типа параметров, записывается имя типа, определенное в заголовке шаблона.
//сравнение двух чисел любого типа
template
T max(T a, T b)
{
if (ab) return a;
else return b;
}
Шаблон служит для автоматического формирования конкретных описаний функций по тем вызовам, которые компилятор обнаруживает в программе. Например, если в программе вызов функции осуществляется как max(1,5), то компилятор сформирует определение функции int max(int a, int b){…}.
Указатель на функцию
Каждая функция характеризуется типом возвращаемого значения, именем и списком типов ее параметров. Если имя функции использовать без последующих скобок и параметров, то он будет выступать в качестве указателя на эту функцию, и его значением будет выступать адрес размещения функции в памяти. Это значение можно будет присвоить другому указателю. Тогда этот новый указатель можно будет использовать для вызова функции.
Указатель на функцию определяется следующим образом:
тип_функции(*имя_указателя)(спецификация параметров)
В определении указателя количество и тип параметров должны совпадать с соответствующими типами в определении функции, на которую ставится указатель.
Вызов функции с помощью указателя имеет вид:
(*имя_указателя)(список фактических параметров);
#include
int f1(char* S)
{
cout
return 1;
}
void main()
{
char s[20]=\nfunction1;
int(*ptr1)(char*); //указатель на функцию
ptr1=f1; //указателю присваивается адрес функции f1
cout
}
Указатели на функции удобно использовать в тех случаях, когда функцию надо передать в другую функцию как параметр.
#include
#include
typedef float(*fptr)(float);//тип-указатель на функцию уравнения
/*решение уравнения методом половинного деления, уравнение передается с помощью указателя на функцию */
float root(fptr f, float a, float b, float e)
{
float x;
do
{
x=(a+b)/2; //находим середину отрезка
if ((*f)(a)*f(x)
b=x;
else a=x;
}
while((*f)(x)efabs(a-b)e);
return x;
}
//функция, для которой ищется корень
float testf(float x)
{
return x*x-1;
}
void main()
{
/*в функцию root передается указатель на функцию, координаты отрезка и точность */
float res=root(testf,0,2,0.0001);
cout
}
Статьи к прочтению:
Параметры по умолчанию. Передача аргументов в функцию по умолчанию. Аргументы по умолчанию. Урок #38
Похожие статьи:
-
Тип возвращаемого значения и параметры функции main
Функция main может иметь тип возвращаемого значения int (задает код возврата программы операционной системе, он может использоваться в пакетных командных…
-
Присвоение начального значения
В том случае, если начальные значения членов структуры известны, можно присвоить их при определении переменной. Если вы создаете только одну переменную…