Локальная область видимости

Правила видимости

Использование функций в выражениях

 

В предыдущем примере значение, возвращенное функций bох(), было присвоено переменной, а затем значение этой переменной выводилось на экран посредством предложения cout. Хотя такое построение программы нельзя назвать неправильным, однако более эффективно было бы использовать возвращаемое значение непосредственно в предложении cout. Так, функцию main( ) из предыдущей программы можно более эффективно переписать следующим образом:

int main() {

// используем возвращаемое из bох( ) значение непосредственно

cout << "Объем равен " << box (10.1, 11.2, 3 . 3 ) ;

return 0;

}

 

Когда выполняется предложение cout, автоматически вызывается функция bох(), что дает возможность получить ее возвращаемое значение. Это значение и выводится на экран. Нет никакого смысла сначала присваивать это значение какой-то переменной.

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

 

// Использование Ьох() в выражении.

 

#include <iostream>

using namespace std;

 

// используем данные типа double

double box(double length, double width, double height);

int main()

{

double sum;

sum = box(10.1, 11.2, 3.3) + box(5.5, 6.6, 7.7) + box(4.0, 5.0, 8.0) ;

 

cout << "Сумма объемов равна " << sum << "\n";

cout << "Среднее значение объема равно " << sum /3.0;

return 0;

}

// Этот вариант box использует данные типа double,

double box(double length, double width, double height) {

return length * width * height ;

}

 

Вывод этой программы:

 

Сумма объемов равна 812.806

Среднее значение объема равно 270.935

 

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

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

 

 

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

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

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

Наиболее распространенным программным блоком, в котором объявляются локальные переменные, является функция. Каждая функция определяет блок кода, который начинается с открывающей функцию фигурной скобки и заканчивается на фигурной скобке, закрывающей функцию. И код, и данные, входящие в функцию, принадлежат этой функции, и к ним не может обратиться никакое предложение в любой другой функции, кроме как путем вызова этой функции. (Например, невозможно, используя предложение goto, перейти в середину другой функции.) Тело функции скрыто от остальной программы, и на него нельзя воздействовать из других частей программы. так же, как и оно не может воздействовать ни на какую другую часть программы. Таким образом, содержимое одной функции полностью отделено от содержимого другой. Можно сказать и по-другому: код и данные, определенные в одной функции, не могут взаимодействовать с кодом и данными, определенными в другой функции, потому что эти две функции имеют различные области видимости.

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

 

#include <iostream>

using namespace std;

 

void f1();

 

int main()

{

int val = 10;// Эта val локальна по отношению к main()

cout << "val в main() : " << val << '\n';

fl() ;

cout << "val в main() : " << val << '\n' ;

return 0 ;

}

 

void fl()

{

val = 88; // Эта val локальна по отношению к f1().

cout << "val в fl{) : " << val << "\n";

}

 

Вот вывод программы:

 

val в main(): 10

val в f1 () : 88

val в main () : 10

 

Переменная, названная val, объявлена дважды, один раз в main() и другой раз в fl(). val в main() никак не влияет на val в fl(), и вообще не имеет к ней никакого отношения. Причина этого в том, что каждая переменная val известна только в той функции, где она объявлена. Как видно из вывода программы, несмотря на то, что при вызове fl() объявленной в ней valприсваивается значение 88, содержимое val в main() остается равным 10.

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

Если объявление локальной переменной включает инициализатор, то эта переменная инициализируется заново при каждом входе в блок. Например:

/*

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

*/

#include <iostream>

using namespace std;

 

void f();

 

int main()

{

for(int i = 0; i < 3; i ++) f() ;

 

return 0 ;

}

 

// num инициализируется при каждом вызове f() .

void f()

{

int num = 99 ;//num присваивается значение 99 при каждом вызове f()

cout << num << "\n";

num++; // результат этого действия не сохраняется

}

 

Вывод программы подтверждает, что num инициализируется при каждом вызове f():

 

 

Локальная переменная, которая не инициализируется при ее объявлении, будет иметь неопределенное значение до тех пор, пока ей не будет что-то присвоено.