Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 04.doc
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
83.46 Кб
Скачать

Void print_arr(int * array, int dim1, int dim2)

{

for (int i = 0; i< dim1; i++)

{

for (int j = 0; j<dim2; j++)

cout << ' ' << array[i*dim2+j];

cout << '\n';

}

}

Void main(void)

{

int m[3][3]= { 1,2,3,

4,5,6,

7,8,9};

print_arr((int*)m,3,3);

// или (почему это дает правильный результат??????)

print_arr(m[0],3,3);

print_arr(*m,3,3);

print_arr(&m[0][0],3,3);

print_arr(&**m,3,3);

getch();

}

Функции overload (перезагружаемые)

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

double sqr (double x) {return x*x;}

можно дополнить функцией

Int sqr(int X) {return X*X;}

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

нужная функция. Какая - решает тип аргумента. Как же это делается? Дело в том,

что историческое название overload (перезагрузка) никакого отношения к действительности не имеет. Просто транслятор в своей работе использует внутренние имена функций, которые содержат в себе скрытое описание типов аргументов. С этими же именами работают программы компоновщика и библиотекаря. Данный механизм и позволяет программам иметь несколько функций с одинаковыми именами, но с разными типами аргументов. Замети, что транслятор не различает функции по типу возвращаемого значения.

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

Если для некоторых аргументов функции можно указать наиболее часто

используемые значения, то С++ позволяет это сделать, избавляя программиста от

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

параметры, имеющие значения по умолчанию, должны располагаться в конце списка параметров. Эти значения будут использованы при вызове функции, если соответствующие параметры окажутся опущенными. Для этого после имени параметра через символ '=' указывается его значение "по умолчанию". Например, у нас есть следующее описание функции:

void print( MATRIX A, char * format = "%9.4f", char * title = NULL);

После этого возможны следующие обращения к функции print:

print(C);

print(C,"%12.7e");

print(C,"%12.7e","__Матрица С__);

Неопределенное число параметров

Существуют функции, в описании которых невозможно указать число и типы

всех допустимых параметров. Тогда список формальных параметров завершается

многоточием ..., что означает: "и, возможно, еще несколько аргументов". Например:

Int printf(const char*, ...);

При вызове printf обязательно должен быть указан параметр типа char*,

однако могут быть (а могут и не быть) еще другие параметры. Например:

printf("Hello, world\n");

printf("My name is %s %s\n", first_name, second_name);

printf("%d + %d = %d\n", 2,3,5);

Такие функции пользуются для распознавания своих фактических параметров недоступной транслятору информацией. В случае функции printf, первый параметр обязателен и является форматной строкой. Она может содержать спецификаторы вывода, которые позволяют функции правильно снимать значения аргументов со стека, которые были туда загружены при обращении к ней. Например, %s означает -"будет фактический параметр типа char*", %d означает -"будет фактический параметр типа int". Но транслятор этого не знает, и поэтому он не может убедиться, что объявленные параметры действительно присутствуют в вызове и имеют соответствующие типы. Например, следующий вызов

char Name[]="Sasha";

printf("My name is %s%d",Name);

нормально транслируется, но приведет (в лучшем случае) к неверному результату при печати.

Очевидно, что раз параметр не описан, то транслятор не имеет сведений для контроля и стандартных преобразований типа этого параметра.

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

int sum(int n,...)

{

int *p=&n+1,s=0,i;

for(i=1;i<=n;i++,p++)

s+=*p;

return s;

}

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

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