Область видимости переменных в C++: локальные и глобальные переменные

Область видимости переменных в C++ Программирование и разработка

Область видимости переменных в C++

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

Декларативный регион и объём

Декларативная область — это самая большая часть текста программы, в которой допустимо имя объекта. Это регион, в котором неквалифицированное имя может использоваться (отображаться) для обозначения одного и того же объекта. Рассмотрим следующую короткую программу:

#include <iostream>
using namespace std;

void fn()
{
int var = 3;
if (1==1)
{
cout<<var<<\n;
}
}

int main()
{
fn();
return 0;
}

Функция fn () имеет два блока: внутренний блок для условия if и внешний блок для тела функции. Идентификатор var вводится и отображается во внешнем блоке. Это также видно во внутреннем блоке с оператором cout. Внешний и внутренний блоки являются областью для имени var.

Однако имя var по-прежнему можно использовать для объявления другой сущности, такой как float, во внутреннем блоке. Следующий код иллюстрирует это:

#include <iostream>
using namespace std;

void fn()
{
int var = 3;
if (1==1)
{
float var = 7.5;
cout<<var<<\n;
}
}

int main()
{
fn();
return 0;
}

Выход 7.5. В этом случае имя var больше не может использоваться во внутреннем блоке для ссылки на целое число значения 3, которое было введено (объявлено) во внешнем блоке. Такие внутренние блоки называются потенциальной областью для сущностей, объявленных во внешнем блоке.

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

Объявление с тем же именем во внутреннем блоке обычно отменяет объявление с тем же именем вне этого внутреннего блока. Во внутренние блоки могут вкладываться другие внутренние блоки.

Глобальная область

Когда программист только начинает печатать файл, это глобальная область видимости. Следующая короткая программа иллюстрирует это:

#include <iostream>
using namespace std;

float var = 9.4;

int main()
{
cout <<var<<\n;
cout <<::var<<\n;

return 0;
}

Результат:
9,4
9,4

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

Блок функции main () имеет другую область видимости; это вложенная область видимости для глобальной области видимости. Для доступа к объекту глобальной области из другой области идентификатор используется непосредственно или перед ним стоит оператор разрешения области, ::.

Примечание. Сущность main () также объявлена ​​в глобальной области видимости.

Область действия блока

Каждый оператор if, while, do, for или switch может определять блок. Такое утверждение является составным утверждением. Имя переменной, объявленной в блоке, имеет область видимости блока. Его область действия начинается в точке объявления и заканчивается в конце блока. Следующая короткая программа иллюстрирует это для переменной идент:

#include <iostream>
using namespace std;

int main()
{
if (1==1)
{
/*some statements*/
int ident = 5;
cout<<ident<<\n;
/*some statements*/
}
return 0;
}

Переменная, такая как идентификатор, объявленная в области блока, является локальной переменной.

Переменная, объявленная вне области видимости блока и выше, может быть видна в заголовке блока (например, условие для блока if), а также внутри блока. Следующая короткая программа иллюстрирует это для переменной identif:

#include <iostream>  
using namespace std;

int main()
{
int identif = 8;

if (identif == 8)
{
cout<<identif<<\n;
}
return 0;
}

Результатом будет 8. Здесь есть две области видимости блока: блок для функции main () и вложенный оператор if-complex. Вложенный блок является потенциальной областью функционального блока main ().

Объявление, введенное в области видимости блока, не может быть видно за пределами блока. Следующая короткая программа, которая не компилируется, иллюстрирует это с помощью переменной variab:

#include <iostream>  
using namespace std;

int main()
{
if (1 == 1)
{
int variab = 15;
}
cout<<variab<<\n;    //error: accessed outside its scope.

return 0;
}

Компилятор выдает сообщение об ошибке для переменной.

Введенная сущность, объявленная в заголовке составной функции, не может быть видна вне (ниже) составного оператора. Следующий код цикла for не будет компилироваться, что приведет к сообщению об ошибке:

#include <iostream>
using namespace std;int main()
{
for (int i=0; i<4; ++i)
{
cout<<i<<‘ ‘;
}
cout<<i<<‘ ‘;

return 0;
}

Переменная итерации i видна внутри блока цикла for, но не вне блока цикла for.

Область функции

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

#include <iostream>
#include <string>
using namespace std;

string fn(string str)
{
char stri[] = «bananas»;
/*other statements*/
string totalStr = str + stri;
return totalStr;
}

int main()
{
string totStr = fn(«eating «);
cout<<totStr<<\n;

return 0;
}

Результат:
есть бананы

Примечание. Сущность, объявленная вне функции (над ней), можно увидеть в списке параметров функции, а также в функциональном блоке.

Объем метки

Объем метки — это функция, в которой она появляется. Следующий код иллюстрирует это:

#include <iostream>
using namespace std;

void fn()
{
goto labl;
/*other statements*/
labl: int inte = 2;
cout<<inte<<\n;
}

int main()
{
fn();

return 0;
}

Выход 2.

Область перечисления

Перечисление без области действия
Рассмотрим следующий блок if:

if (1==1)
{
enum {a, b, c=b+2};
cout<<a<<‘ ‘<<b<<‘ ‘<<c<<\n;
}

На выходе будет 0 1 3.

Первая строка в блоке — это перечисление, a, b и c — его перечислители. Область действия перечислителя начинается с точки объявления до конца включающего блока перечисления.

Следующий оператор не будет компилироваться, потому что точка объявления c находится после точки объявления a:

enum {a=c+2, b, c};

Следующий сегмент кода не будет компилироваться, поскольку доступ к перечислителям осуществляется после включающего блока перечисления:

if (1==1)
{
enum {a, b, c=b+2};
}
cout<<a<<‘ ‘<<b<<‘ ‘<<c<<\n;  //error: out of scope

Вышеупомянутое перечисление описывается как перечисление без области действия, а его перечислители описываются как перечислители без области действия. Это потому, что он начинается только с зарезервированного слова enum. Перечисления, которые начинаются с класса перечисления или структуры перечисления, описываются как перечисления с ограниченной областью действия. Их счетчики описываются как счетчики с заданной областью действия.

Перечисление с областью действия

Следующее утверждение подходит:

enum class nam {a, b, c=b+2};

Это пример перечисления с ограниченной областью видимости. Имя класса — nam. Здесь область действия перечислителя начинается с точки объявления до конца определения перечисления, а не от конца включающего блока для перечисления. Следующий код не компилируется:

if (1==1)
{
enum class nam {a, b, c=b+2};
cout<<a<<‘ ‘<<b<<‘ ‘<<c<<\n;   //error: out of scope for enum class or enum struct  
}

Область действия класса

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

#include <iostream>
using namespace std;

//Base class
class Cla
{
private:
int memP = 5;
protected:
int memPro = 9;
public:
void fn()
{
cout<<memP<<\n;
}
};

//Derived Class
class DerCla: public Cla
{
public:
int derMem = memPro;
};
int main()
{
Cla obj;
obj.fn();
DerCla derObj;
cout<<derObj.derMem<<\n;

return 0;
}

Результат:
5
9

В классе Cla переменная memP видна в точке объявления. После этого короткая часть «protected» пропускается, а затем снова отображается в функциональном блоке-члене класса. Производный класс пропускается, а затем снова отображается в области (блоке) функции main ().

В классе Cla переменная memPro видна в точке объявления. Часть общедоступной функции fn () пропускается, а затем отображается в блоке описания производного класса. Это снова видно в функции main ().

Оператор разрешения области действия

Оператором разрешения области действия в C ++ является ::. Он используется для доступа к статическому члену класса. Следующая программа иллюстрирует это:

#include <iostream>
using namespace std;

class Cla
{
public:
static int const mem = 5;
public:
static void fn()
{
cout<<mem<<\n;
}
};
int main()
{
cout<<Cla::mem<<\n;
Cla::fn();

return 0;
}

Результат:
5
5

Статические члены видны в функциональном блоке main (), доступ к которому осуществляется с помощью оператора разрешения области видимости.

Область действия параметра шаблона

Обычная область действия имени параметра шаблона начинается с момента объявления до конца его блока, как в следующем коде:

template<typename T, typename U>  struct Ages
{
T John = 11;
U Peter  = 12.3;
T Mary  = 13;
U Joy   = 14.6;
};

U и T видны внутри блока.

Для прототипа шаблонной функции область действия начинается от точки объявления до конца списка параметров функции, как в следующем заявлении:

template<typename T, typename U> void func (T no, U cha, const char *str );

Однако, когда дело доходит до описания (определения) класса, область видимости также может состоять из разных частей, как в следующем коде:

#include <iostream>
using namespace std;

template<class T, class U> class TheCla
{
public:
T num;
static U ch;

void func (U cha, const char *str)
{
cout << «There are « << num << » books worth « << cha << str << » in the store.» << \n;
}
static void fun (U ch)
{
if (ch == ‘a’)
cout << «Official static member function» << \n;
}
};

int main()
{
TheCla<intchar> obj;
obj.num = 12;
obj.func(‘$’«500»);

return 0;
}

Скрытие имени

Пример сокрытия имени происходит, когда имя того же типа объекта повторно объявляется во вложенном блоке. Следующая программа иллюстрирует это:

#include <iostream>
using namespace std;

void fn()
{
int var = 3;
if (1==1)
{
int var = 4;
cout<<var<<\n;
}
cout<<var<<\n;
}

int main()
{
fn();
return 0;
}

Результат:
4
3

Это потому, что var во вложенном блоке спрятал var во внешнем блоке.

Возможность повторения декларации в том же объеме

Смысл объявления в том, что имя вводится (впервые) в его область видимости.

Прототип функции

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

#include <iostream>
using namespace std;

void fn(int num);
void fn(int num);

void fn(int num)
{
cout<<num<<\n;
}

int main()
{
fn(5);

return 0;
}

Программа работает.

Перегруженные функции

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

#include <iostream>
using namespace std;

void fn(int num)
{
cout<<num<<\n;
}

void fn(float no)
{
cout<<no<<\n;
}

int main()
{
fn(5);
float flt = 8.7;
fn(flt);

return 0;
}

Результат:
5
8,7

Перегруженные функции определены в глобальной области.

Область действия пространства имен

Область действия пространства имен заслуживает отдельной статьи. Указанная статья написана для этого веб-сайта linuxhint.com. Просто введите поисковые слова «Namespace Scope» в поле поиска на этом сайте (странице) и нажмите «ОК», и вы получите статью.

Объем в разных частях

Класс — не единственная схема, в которой область видимости может быть в разных частях. Спецификатор друга, определенные варианты использования спецификатора детализированного типа и директивы using — это другие схемы, в которых область видимости находится в разных местах — подробности см. Ниже.

Заключение

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

Читайте также:  Список массивов в Java
Оцените статью
bestprogrammer.ru
Добавить комментарий