C++標識符的作用域與可見性


一、標識符的作用域與可見性

作用域討論的是標識符的有效范圍,可見性討論的是標識符是否可以被引用。

二、作用域

作用域是一個標識符在程序正文中有效的區域。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.mX::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 的方式引用,為其賦值。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM