Автор работы: Пользователь скрыл имя, 14 Декабря 2013 в 21:32, реферат
Каждое имя в С++ программе должно относиться к уникальной сущности (объекту, функции, типу или шаблону). Это не значит, что оно встречается только один раз во всей программе: его можно повторно использовать для обозначения другой сущности, если только есть некоторый контекст, помогающий различить разные значения одного и того же имени. Контекстом, служащим для такого различения, служит область видимости. В С++ поддерживается три их типа:локальная область видимости, область видимости пространства имен и область видимости класса. Локальная область – это часть исходного текста программы, содержащаяся в определении функции (или в блоке). Любая функция имеет собственную такую часть, и каждая составная инструкция (или блок) внутри функции также представляет собой отдельную локальную область.
Ахметов Ниязбек, гр.163
г. Томск
Каждое имя
в С++ программе должно относиться к уникальной
сущности (объекту, функции, типу или шаблону).
Это не значит, что оно встречается только
один раз во всей программе: его можно
повторно использовать для обозначения
другой сущности, если только есть некоторый
контекст, помогающий различить разные
значения одного и того же имени. Контекстом,
служащим для такого различения, служит
область видимости. В С++ поддерживается
три их типа:локальная область видимости,
область видимости пространства имен
и область видимости
класса.
Локальная область –
это часть исходного текста программы,
содержащаяся в определении функции (или
в блоке). Любая функция имеет собственную
такую часть, и каждая составная инструкция
(или блок) внутри функции также представляет
собой отдельную локальную
область.
Область видимости пространства
имен – часть исходного текста программы,
не содержащаяся внутри объявления или
определения функции или определения
класса. Самая внешняя часть называется
глобальной областью видимости или глобальной
областью видимости пространства
имен.
Объекты, функции, типы
и шаблоны могут быть определены в глобальной
области видимости. Программисту разрешено
задать пользовательские пространства
имен, заключенные внутри глобальной области
с помощью определения пространства
имен. Каждое такое пространство является
отдельной областью видимости. Пользовательское
пространство, как и глобальное, может
содержать объявления и определения объектов,
функций, типов и шаблонов, а также вложенные
пользовательские пространства имен.
Каждое определение класса
представляет собой отдельную область
видимости класса.
Имя может обозначать
различные сущности в зависимости от области
видимости. В следующем фрагменте программы
имя s1 относится к четырем разным сущностям:
#include <iostream>
#include <string>
// сравниваем s1 и s2 лексикографически
int lexicoCompare( const string &sl, const string &s2 ) { ... }
// сравниваем длины s1 и s2
int sizeCompare( const string &sl, const string &s2 ) { ... }
typedef int ( PFI)( const string &, const string & );
// сортируем массив строк
void sort( string *s1, string *s2, PFI compare =lexicoCompare )
{ ... }
string sl[10] = { "a", "light", "drizzle", "was", "falling",
"when", "they", "left", "the", "school" };
int main()
{
// вызов sort() со значением по умолчанию параметра compare
// s1 - глобальный массив
sort( s1, s1 + sizeof(s1)/sizeof(s1[0]) - 1 );
// выводим результат сортировки
for ( int i = 0; i < sizeof(s1) / sizeof(s1[0]); ++i )
cout << s1[ i ].c_str() << "\n\t";
}
Поскольку определения
функций lexicoCompare(), sizeCompare() и sort() представляют
собой различные области видимости и все
они отличны от глобальной, в каждой из
этих областей можно завести переменную
с именем s1.
Имя, введенное с
помощью объявления, можно использовать
от точки объявления до конца области
видимости (включая вложенные области).
Так, имя s1 параметра функции lexicoCompare()
разрешается употреблять до конца ее области
видимости, то есть до конца ее определения.
Имя глобального
массива s1 видимо с точки его объявления
до конца исходного файла, включая вложенные
области, такие, как определение функции
main().
В общем случае имя должно
обозначать одну сущность внутри одной
области видимости. Если в предыдущем
примере после объявления
массива s1 добавить следующую строку,
компилятор выдаст сообщение об ошибке:
void s1(); // ошибка: повторное объявление s1
Перегруженные
функции являются исключением из правила:
можно завести несколько одноименных
функций в одной области видимости,
если они отличаются списком параметров.
В С++ имя должно быть
объявлено до момента его первого использования
в выражении. В противном
случае компилятор выдаст сообщение об
ошибке. Процесс сопоставления имени,
используемого в выражении, с его объявлением
называется разрешением. С помощью этого
процесса имя получает конкретный смысл.
Разрешение имени зависит от способа его
употребления и от его области видимости.
Мы рассмотрим этот процесс в различных
контекстах.
Области видимости и
разрешение имен – понятия
времени компиляции. Они применимы к отдельным
частям текста программы. Компилятор интерпретирует
текст программы согласно правилам областей
видимости и правилам разрешения имен.
Локальная область видимости:
Локальная область видимости – это часть исходного текста программы, содержащаяся в определении функции (или блоке внутри тела функции). Все функции имеют свои локальные области видимости. Каждая составная инструкция (или блок) внутри функции также представляет собой отдельную локальную область. Такие области могут быть вложенными. Например, следующее определение функции содержит два их уровня (функция выполняет двоичный поиск в отсортированном векторе целых чисел):
const int notFound = -1; // глобальная область видимости
int binSearch( const vector<int> &vec, int val )
{ // локальная область видимости: уровень #1
int low = 0;
int high = vec.size() - 1;
while ( low <= high )
{ // локальная область видимости: уровень #2
int mid = ( low + high ) / 2;
if ( val < vec[ mid ] )
high = mid - 1;
else low = mid + 1;
}
return notFound; // локальная область видимости: уровень #1
}
Первая локальная
область видимости – тело функции binSearch().
В ней объявлены параметры функции vec и
val, а также переменные
low и high. Цикл while внутри функции задает
вложенную локальную область, в которой
определена одна переменная mid. Параметры
vec и val и переменные low и high видны во вложенной
области. Глобальная область видимости
включает в себя обе локальных.
В ней определена одна целая константа
notFound.
Имена параметров функции
vec и val принадлежат к первой локальной
области видимости тела
функции, и в ней использовать те же имена
для других сущностей нельзя. Например:
int binSearch( const vector<int> &vec, int val )
{ // локальная область видимости: уровень #1
int val; // ошибка: неверное переопределение val
// ...
Имена параметров
употребляются как внутри тела функции
binSearch(), так и внутри вложенной области
видимости цикла while. Параметры vec
и val недоступны вне тела функции binSearch().
Разрешение имени в локальной
области видимости происходит следующим
образом: просматривается та область,
где оно встретилось. Если объявление
найдено, имя разрешено. Если нет, просматривается
область видимости, включающая
текущую. Этот процесс продолжается до
тех пор, пока объявление не будет найдено
либо не будет достигнута глобальная область
видимости. Если и там имени нет, оно будет
считаться ошибочным.
Из-за порядка просмотра
областей видимости в процессе
разрешения имен объявление из внешней
области может быть скрыто объявлением
того же имени во вложенной области. Если
бы в предыдущем примере переменная low
была объявлена в глобальной области видимости
перед определением функции binSearch(), то
использование low в локальной
области видимости цикла while все равно
относилось бы к локальному объявлению,
скрывающему глобальное:
int low;
int binSearch( const vector<int> &vec, int val )
{
// локальное объявление low
Пример
Если определить переменную внутри блока , ее время существования и область существования ограничиваются этим блоком. Предположим что в начале main () определена переменная teledeli. Теперь пусть в main () создается новый блок, в котором определяется новая переменная по имени websight. В этом случае переменная teledeli является видимой как во внешнем так и во внутреннем блоке , в то время как websight существует только во внутреннем блоке и находится в области видимости с точки своего определения до тех пор, пока выполнение программы не доберется до конца блока:
int main ()
{
int teledeli=5;
{ // Переменной websight выделяется память
cout<<” hello \n”;
int websight = -2; // начинается область видимости websight
cout<< websight<<’ ’<<teledeli<<endl;
}
cout<< teledeli<<endl;
} // Переменная teledeli прекращает существования
Вывод на экран:
Hello
-2 5
5
А что если переменной во внутреннем блоке назначить имя teledeli вместо websight, в результате чего получится две переменных с одним и тем же именем, одна из которых находится во внешнем блоке, а другая – во внутреннем? В этом случае программа интерпретирует имя teledeli как переменную, локальную по отношению к блоку, во время выполнения операторов этого блока. Принято говорить, что новое определение скрывает предыдущее. Новое определение попадает в область видимости, а предыдущее из нее временно удаляется. Когда выполнение программы покидает блок, исходное определение возвращается обратно в область видимости.