пользователей: 28278
предметов: 12134
вопросов: 228408
Конспект-online
РЕГИСТРАЦИЯ ЭКСКУРСИЯ

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

Функция. Прототип

Функция в C++ объявляется, определяется, вызывается. В разделе, посвящённом структуре программного модуля, в качестве примера мы уже рассматривали синтаксис определения функции. Определение функции состоит из заголовка и тела. Заголовок функции состоит из спецификаторов объявления, имени функции и списка параметров. Тело функции образуется блоком операторов.

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

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

#include <iostream.h>

void ZZ(int param) // Определение функции.

{

 cout << "This is ZZ >> " << param << endl;

}

void main (void)

{

ZZ(10); // Вызов функции. Транслятор уже знает о функции всё.

}

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

#include <iostream.h>

#include "zz.cpp"

/*

Препроцессор к моменту трансляции "подключает" определение функции ZZ() из файла zz.cpp.

*/

void main (void)

{

ZZ(125);

}

Файл zz.cpp:

void ZZ(int par1)

{

 cout << "This is ZZ " << par1 << endl;

}

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

#include <iostream.h>

void main (void)

{

ZZ(10);

/* Здесь транслятор сообщит об ошибке. */

}

void ZZ(int param)

{

 cout << "This is ZZ " << param << endl;

}

Каждая функция, перед тем, как она будет вызвана, по крайней мере, должна быть объявлена. Это обязательное условие успешной трансляции и вольный перевод соответствующего сообщения об ошибке (Call to undefined function 'ИмяФункции'), выдаваемого транслятором в случае вызова необъявленной функции.

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

#include <iostream.h>

void ZZ(int ppp);

/*

Эта строка требуется для нормальной компиляции программы.

Это и есть прототип функции. Имя параметра в объявлении может

не совпадать с именем параметра в определении.

*/

void main (void)

{

ZZ(125);

}

void ZZ(int par1)

{

 cout << "This is ZZ " << par1 << endl;

}

Самое интересное, что и такое объявление не вызывает возражений транслятора.

#include <iostream.h>

void ZZ(int);

/*

Отсутствует имя параметра. Можно предположить, что имя параметра

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

*/

void main (void)

{

ZZ(125);

}

void ZZ(int par1)

{

 cout << "This is ZZ " << par1 << endl;

}

Правила грамматики подтверждают это предположение. Ранее соответствующее множество БНФ уже рассматривалось:

ОбъявлениеПараметра ::= СписокСпецификаторовОбъявления Описатель

                    ::= СписокСпецификаторовОбъявления

                                                Описатель

                                                  Инициализатор

                    ::= СписокСпецификаторовОбъявления

                                             [АбстрактныйОписатель]

                                                      [Инициализатор]

Из этой формы Бэкуса-Наура следует, что объявление параметра может состоять из одного спецификатора объявления (частный случай списка спецификаторов). Так что имени параметра в списке объявления параметров в прототипе функции отводится в букальном смысле роль украшения. Его основное назначение в прототипе - обеспечение легкочитаемости текста программы. Принципиальное значение имеет соответствие типов параметров в определении и объявлении функции.

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

#include <iostream.h>

void ZZ(float);// Другой тип параметра.

void main (void)

{

ZZ(125);

}

void ZZ(int par1)

{

 cout << "This is ZZ " << par1 << endl;

}

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

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


27.12.2014; 11:23
хиты: 35
рейтинг:0
Точные науки
информатика
Языки программирования
для добавления комментариев необходимо авторизироваться.
  Copyright © 2013-2018. All Rights Reserved. помощь