內部連結 Internal Linkage
這章我們要來介紹內部連結 internal linkage,包括它是什麼、要怎麼用它等等。
廢話不多說,就讓我們趕快來學習吧!
什麼是內部連結
不知道你們有沒有想過,為什麼在一個檔案裡面的變數只有該檔案才看得到,其他檔案看不到?
你們可能會想:「誒這不是很合理嗎?」
沒錯!這很合理!如果不是這樣的話那如果有成千上萬個檔案的話那就會非常混亂了。
但其實這個背後有一個原因,那就是內部連結!
內部連結的意義在於,如果一個變數或函數被設定為內部連結,那麼只有該檔案可以看得到它。
聰明的你可能會問,那我們什麼時候會需要其他檔案看得到它?
誒不用急,我們會在下一篇專門講解內部連結的兄弟,外部連結。這章就讓我們專心在內部連結吧!
但其實,並不是所有變數都是預設為內部連結的喔!讓我們接下來看下去。
全局變數
全局變數,中文叫做 global variable。從名字我們就可以感覺到,所有檔案都可以讀到它。
那我們應該要如何建立一個全局變數呢?
在以前,我們一直都是在 main()
函數裡面建立變數。但其實, 我們也可以在 main()
函數之外建立變數!
而在 main()
函數之外建立的變數,如果沒有額外的關鍵字,那麼就會是一個全局變數。而全局變數預設就不是內部連結!
比方說:
// 全局變數 global variable int a{0}; int main() { int b{0}; return 0; }
我們可以將這個全局變數改為內部連結,有兩個方法:
static
const
// 擁有內部連結的全局變數 static int a{0}; const int c{0}; int main() { int b{0}; return 0; }
static
這個關鍵字沒什麼好說的,就是一個強制宣稱變數擁有內部連結的機制而已。
但 const
是什麼?關鍵字 const
其實是 constant 的縮寫,代表固定值,也就是絕對不能夠被改變。
因此如果我嘗試改變變數 c
的值,程式就會報錯!
const int c{0}; int main() { c = 3; // 程式會報錯! return 0; }
那為什麼被宣告為固定值的變數預設不能被其他文件看到呢?
其實很好理解,這是因爲其他文件並不會知道這個變數被宣告為固定值。因此可能會想要去改變它,而我們知道一但嘗試改變它,就會報錯。
我們可以做一個小實驗來證實擁有內部連結的全局變數。我們來創建兩個 .cpp
檔案:
test.cpp
:
const int a{1};
main.cpp
:
static int a{5}; int main() { std::cout << a << std::endl; return 0; }
我們會看到程式碼會印出數字 5。
函數
有發現嗎?我們之前在寫函數時都寫在 main()
的外面。所以函數其實預設是擁有外部連結的!
我們一樣也可以用關鍵字 static
將函數改為擁有內部連結。
test.cpp
:
static int print() { std::cout << "This is from test.cpp" << std::endl; }
main.cpp
:
static int print() { std::cout << "This is from main.cpp" << std::endl; } int main() { print(); return 0; }
我們可以發現結果為:
This is from main.cpp
為什麼要內部連結
其實內部連結主要提供了兩個主要好處:
- 有一個我們想確保不被其他文件讀取的東西。這可能是一個我們不想被干擾的全局變數,或者是一個我們不希望被調用的函數。
- 避免命名衝突。因為具有內部連結的變數或函數名稱不會暴露給連結器,因此它們只可能與在同一文件中的名稱發生衝突,而不是整個大專案中的其他幾百幾千個文件。
我個人的建議是,如果一個變數或函數並不需要被外部的文件取用的話,就一律將他們設定為擁有內部連結!
這在小型的個人專案中可能不會造成什麼影響,但在大型專案中,會大大的減少許多意想不到的錯誤的可能性!
總結
這章我們了解了一個全新的概念,內部連結,包括它為什麼存在、它長怎麼樣、它的應用等等。
這個東西其實概念不難,但我們很常在寫程式碼時忘記這個簡單又重要的規則,導致程式出錯。
下一章我們會來介紹外部連結~