一、標識符的作用域與可見性
作用域討論的是標識符的有效范圍,可見性討論的是標識符是否可以被引用。
二、作用域
作用域是一個標識符在程序正文中有效的區域。C++中標識符的作用域有函數原型作用域、局部作用域(塊作用域)、類作用域和命名空間作用域。
1.函數原型作用域
C++程序中最小的作用域。在函數原型聲明時形式參數的作用范圍就是函數原型作用域。
例:
double area{double radius};//標識符radius
注:標識符radius的作用域范圍就是在函數area形參列表的左右括號之間,在程序的其他地方不能引用這個標識符。
在函數原型的形參列表中起作用的只是形參類型,標識符並不起作用,因此可以省略標識符,但為了程序的可讀性,通常在函數原型聲明時給出標識符。
2.局部作用域
①函數形參列表中的形參的作用域,從形參列表中的聲明處開始,到整個函數體結束之處為止。
②函數體內聲明的變量,其作用域從聲明處開始,一直到聲明所在的塊結束的大括號為止。
具有局部作用域的變量也稱局部變量。
void fun(int a){//a的作用域整個函數體
int b=a;//b的作用域大括號里
cin>>b; if (b<0){ int c;//c的作用域 if的大括號里
... } }
再例:
#include <iostream> using namespace std; void anotherFunction() ; //函數原型 int main() { int num = 1; //主函數main中的num cout << "In main, num is " << num << endl; anotherFunction(); cout << "Back in main, num is still " << num << endl; return 0; } void anotherFunction() { int num = 20; //函數anotherFunction中的num cout << "In anotherFunction, num is " << num << endl; }
注:雖然有兩個名為 num 的變量,但是程序在同一時間只能“看到”其中一個,因為它們在不同的函數中。
兩個函數的封閉性質,“{}”分隔變量的作用域。第一個main變量僅在main函數中可見;第二個num僅在anotherFunction函數中可見。

3.類的作用域
類可以被看成一組有名成員的集合,類X的成員m具有類的作用域,對m的訪問有如下三種方式:、
①如果X的成員函數中沒有聲明同名的局部作用域標識符,那么可以直接訪問m。也就是說m在這樣的函數中都起作用。
Clock globClock; globClock.showtime();//對象的成員函數具有類的作用域
②通過表達式x.m或X::m。這是訪問對象成員的最基本方法。X::m的方式用於訪問類的靜態成員。
void Clock::showtime()
③使用ptr->m,其中ptr為指向X類的一個對象的指針。
Student *student = new Student(); student->show();
4.命名空間作用域
命名空間的語法形式:
namespace 命名空間名{ 命名空間內的各種聲明(函數聲明、類聲明......) }
注:
一個命名空間確定了一個命名空間的作用域,凡是在該命名空間之內聲明的、不屬於前面所述各個作用域的標識符,都屬於該命名空間作用域。
①如需在該命名空間內需要引用其他命名空間的標識符,語法形式如下:
命名空間名::標識符
namespace SomeNs{ class SomeClass{...}; } //如需引用類名SomeClass或函數名someFunc
SomeNs::SomeClass obj1;//聲明一個SomeNS型的對象obj1
②為了避免標識符前總使用上面的命名空間限定顯得冗長,C++提供了using語句
兩種形式
using 命名空間名::標識符名;//將指定的標識符暴露在當前作用域內,使得在當前作用域內可以直接使用該標識符
using namespace 命名空間名;//將指定命名空間內的所有標識符暴露在當前作用域內,使得在該命名空間內可以直接使用任何標識符
③命名空間允許嵌套
namespace OuterNs{ namespace InnerNs{ class SomeClass(...); } }
④特殊的命名空間:全局命名空間和匿名命名空間
全局命名空間:是默認的的命名空間,在顯式聲明的命名空間之外生命的標識符都在一個全局命名空間中
匿名命名空間:是一個需要顯式聲明的沒有名字的命名空間,例如:
namespace{ 匿名命名空間內的各種聲明(函數聲明、類聲明、......) }
二、可見性
定義:程序運行到某一點,能夠引用到的標識符,就是該處可見的標識符。
作用域可見性的一般規則如下:
①標識符要聲明在前,引用在后
②在同一作用域中不能聲明同名的標識符
③在沒有互相包含關系的不同的作用域中聲明的同名標識符,互不影響
④如果在兩個或者多個具有包含關系的作用域中聲明了同名標識符,則外層標識符在內層不可見
三、程序實例
#include <iostream> using namespace std; int i; //在全局命名空間中的全局變量 namespace Ns{ int j; //在Ns命名空間中的全局變量 } int main(){ i=5; //為全局變量i賦值 Ns::j=6; //為全局變量j賦值 { using namespace Ns; //使當前塊中可以直接引用Ns命名空間的標識符 int i; //局部變量,局部作用域 i=7; cout<<"i="<<i<<endl; cout<<"j="<<j<<endl; } cout<<"i="<<i<<endl; return 0; }

注意:5-1中聲明的全局變量就是具有命名空間的作用域,他們在整個文件中都有效。(具有命名空間作用域的變量也成為全局變量)
①變量 i 是全局命名空間,有效范圍直到文件尾。
②在主函數開始處給 i 賦初值5,接下來又聲明了同名變量並賦初值7。第一次輸出的結果是7,因為具有局部作用域的變量 i 把具有命名空間作用域的 i 隱藏了,於是具有命名空間作用域的 i 變得不可見。
③第一個塊運行結束,輸出的 i 的值為7,因為具有局部作用域的 i 不在有效范圍之內了,現在處在有效范圍內的變量只有具有命名空間作用域的那個變量。
④j被聲明在命名空間 Ns 中,在主函數中通過 Ns::j 的方式引用,為其賦值。
