單定義規則與作用域

作用域描述了名稱在文件多大範圍內可見。C++ primer plus中還有一個定義是鏈接性,鏈接性描述了名稱如何在不同文件間共享。其實我個人理解,鏈接性跟作用域描述的概念差不多,只不過一個是對文件內部可見性(訪問)的描述,一個是對文件之間可見性(訪問)的描述。

單定義規則,根據網上大部分的描述是,任何變量都只能定義一次,比如定義了int a,不能再重新定義一個int a,只能賦值。這顯然是不嚴謹的,因爲我們可以在不同的函數中定義同名的變量。

應該說,任何時候都只能存在一個相對可見的定義。

首先我們先來分析一下各種變量的作用域。

1、自動變量。如果在代碼塊中定義了變量,則該變量的存在時間和作用域都被限制在了該代碼塊內,該變量沒有鏈接性。並且,在該代碼塊內,該變量會隱藏其他在代碼塊外部定義的同名變量。也就是說在該代碼塊內部,只有內部的定義是可見的,在代碼塊外部,只有外部的定義是可見的,所以,在代碼塊內部定義同名變量並不會違反單定義規則。

2、靜態持續變量。靜態持續變量的存在時間爲整個程序執行期間,但是它的作用域和鏈接性取決於定義方式,定義方式有如下三種:

2.1、如果在所有函數外面定義一個變量,例如

//file1.cpp
int a;
int main()
{
return 0;
}

那麼a就是一個全局變量,它的作用域爲全文件,鏈接性爲外部,也就是說它在其他的文件中也能共享(可見),只要加一個extern聲明就行。

如果是這樣的定義方式的話,那麼在程序的其他文件中,也就是它的可見範圍內,就不能在定義一個跟他同名的全局變量了。

2.2、如果採用下面這種方式在所有的函數外面定義一個變量,例如

//file2.cpp
static int a;
int main()
{
return 0;
}
那麼a是一個靜態全局變量,它的作用域爲全文件,鏈接性爲內部,也就是說它在其他文件中不能共享(不可見)。那麼file1和file2一起編譯,會不會出現錯誤呢?答案是不會,就像局部變量會在自己的代碼塊中隱藏外部的同名變量一樣,file2中的a也會隱藏file1中的全局變量a的定義。在file2中,只有該文件中定義的a可見,而在其他文件中,file2中的a是不可見的,只有file1中的全局變量a可見。因此我們上面也說了,不能對全局變量定義兩次(不能定義兩個同名的全局變量)。

2.3、如果是在代碼塊中定義的靜態局部變量,那麼除了存在時間,它的行爲跟局部變量是一樣的。


關於函數,和變量一樣,函數也有鏈接性。和c語言一樣,c++不允許在一個函數的內部定義另一個函數,因此,所有函數的持續性都是靜態的,即在程序執行期間都是存在的。默認情況下,函數的鏈接性爲外部,即可以在文件間共享(可見)。還可以像變量一樣,使用static將函數的鏈接性設置爲內部,使之只能在一個文件中使用。必須同時在函數原型和函數定義前加上關鍵字static。這意味着該函數只在這個文件是可見的,還意味着可以在別的文件中定義一個跟他同名的函數。

所以,單定義規則嚴格來說應該是,只有一個相對可見的定義


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章