Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
http.doc
Скачиваний:
0
Добавлен:
11.01.2020
Размер:
1.34 Mб
Скачать

Сопоставление классического и современного объявления параметров

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

Классический способ объявления параметров функций состоит из двух частей: списка параметров, находящихся в круглых скобках, следующих за именем функции, и собственно объявления параметров, которое происходит между закрывающей круглой и открывающей фигурной скобкой. Ниже приведен общий вид классического определения параметров: тип имя_функции (параметр1, параметр2, ..., параметрN) тип параметр1; тип параметр2; ... тип параметрN; { код функции }

Ниже показан пример современного объявления: char *f(char *str1, int count, int index) { .... }

При классическом объявлении эта же функция будет выглядеть так: char *f(str1, count, index) char *str1; int count, index; { ... } Обратим внимание, что в классическом способе может присутствовать более одного параметра после имени.

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

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

Чаще всего к ошибкам приводит использование указателей па функцию. Хотя функция - это не переменная, она по-прежнему имеет физическое положение в памяти, которое может быть присвоено указателю. Адрес, присвоенный указателю, является входной точкой в функцию. Указатель может использоваться вместо имени функции. Он также позволяет передавать функции как обычные аргументы в другие функции.

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

Адрес функции получается при использовании имени функции без каких-либо скобок или аргументов. (Очень похоже на массивы, где адрес получается с использованием имени массива без индексов.) Рассмотрим следующую программу, предназначенную для демонстрации нюансов объявления: #include <stdio.h> #include <string.h> void check(char *a, char *b, int (*cmp) (const char *, const char *)); int main(void) { char s1 [80], s2[80]; int (*p) (const char*, const char*); p = strcmp; /* получение адреса strcmp() */ gets(s1); gets (s2); check(s1, s2, p); return 0; } void check (char *a, char *b, int (*cmp) (const char *, const char *)) { printf("Testing for equality.\n"); if(!(*cmp) (a, b)) printf("Equal"); else printf("Not equal"); }

Когда вызывается check(), ей передаются два указателя на символы и один указатель на функцию. В функции check() аргументы объявляются как указатели на символы и указатель на функцию. Надо обратить внимание на способ объявления указателя на функцию. Следует использовать аналогичный метод при объявлении других указателей на функцию, за исключением тех случаев, когда отличается возвращаемый тип или передаваемые параметры. Скобки вокруг *cmp необходимы для правильной интерпретации компилятором данного выражения.

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

Рассмотрим работу функции strcmp() в функции check(). Оператор if (!(*cmp) (a, b) ) printf("Equal"); осуществляет вызов функции, в данном случае strcmp(), с помощью cmp, который указывает на данную функцию. Вызов происходит с аргументами a и b. Данный оператор демонстрирует общий вид использования указателя на функцию для вызова функции, на которую он указывает. Круглые скобки вокруг *cmp необходимы вследствие наличия приоритетов. На самом деле можно напрямую использовать cmp, как показано ниже: if (!cmp(a, b)) printf("Equal"); Данная версия также вызывает функцию, на которую указывает cmp, но она использует нормальный синтаксис. Использование ( cmp) помогает всем, читающим программу, понять, что указатель на функцию используется для вызова функции вместо вызова функции cmp. Возможно вызвать напрямую check(), используя strcmp, как показано ниже: check(s1, s2, strcmp); Данный оператор устраняет необходимость наличия дополнительной переменной-указателя.

Можно задаться вопросом, почему кто-то хочет написать программу таким способом. В данном примере ничего не достигается, но появляются большие проблемы. Тем не менее иногда бывают моменты, когда выгодно передавать функции в процедуры или хранить массивы функций. Следующий пример демонстрирует использование указателей на функции. При написании интерпретатора наиболее типично использование вызовов функций для различных подпрограмм поддержки, типа синус, косинус и тангенс. Вместо использования большого списка для оператора switch, можно использовать массив указателей на функции, в котором доступ к необходимой функции осуществляется с помощью индекса. В данной программе check() может использоваться для проверки как алфавитного, так и численного равенства простым вызовом различных функций сравнения. #include <stdio.h> #include <ctype.h> #include <string.h> #include <stdlib.h> void check(char *a, char *b, int (*cmp) (const char *, const char *)); int numcmp (const char *a, const char *b) ; int main(void) { char s1[80], s2 [80]; gets (s1); gets (s2); if(isalpha(*s1)) check (s1, s2, strcmp); else check(s1, s2, numcmp); return 0; } void check(char *a, char *b, int (*cmp) (const char *,const char *)) { printf("Testing for equality.\n"); if(!(*cmp) (a, b)) printf ("Equal"); else printf("Hot equal"); } int numcmp (const char *a, const char *b) { If(atoi(a)==atoi(b)) return 0; else return 1; }

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