C++中關(guān)于函數(shù)的extern鏈接性以及extern關(guān)鍵字
C++中extern關(guān)鍵字主要有三種作用,即聲明變量的鏈接性、函數(shù)的鏈接性、以及語言的鏈接性。所謂的鏈接性(linkage)是指名稱如何在不同的編譯單元間共享。與其相應(yīng)的是作用域(scope),它描述的是名稱在一個編譯單元的多大范圍內(nèi)可見。
變量的鏈接性:由于C++中變量具有單定義規(guī)則(one definiton rule)(只能被定義一次),那么在同一個工程的其他文件中,如果要想使用一個已經(jīng)定義的變量,只能使用聲明(declaration)。一個全局變量的默認(rèn)鏈接性是只在本文件可見,在另外一個文件中可以使用extern來聲明這個變量,表示該變量已經(jīng)在它處定義,從而使得該變量在“變量聲明”所在的文件同樣可見,達到共享的目的。
函數(shù)的鏈接性:默認(rèn)情況下函數(shù)的鏈接性是外部的,即可以在文件間共享。可以使用extern來指出這一點,即該函數(shù)是在另外一個文件中定義的,不過這是可選的。但是如果用static來修飾函數(shù)的話,那么其鏈接性就是內(nèi)部的。
如果用static修飾函數(shù)的鏈接性,必須同時給出函數(shù)原型以及定義。
static int private(double x);
...
static int private(double x)
{
...
}
語言的鏈接性:在C語言中函數(shù)是不能重載的,因此在編譯后,一個函數(shù)名對應(yīng)于一個翻譯后的符號名,例如 test(int),對應(yīng)于_test。但是C++是可以重載的,因此函數(shù)經(jīng)編譯器翻譯后的名稱會有所不同。例如會將test(int),對應(yīng)于_test_i。但是可以使用extern “C”來告訴編譯器不要按照C++默認(rèn)的方式翻譯,而使用類似于C的方式翻譯。
下面通過示例來具體說下函數(shù)的鏈接性。
首先,函數(shù)的默認(rèn)鏈接性是外部的。
//func.cpp
#include <iostream>
void func()
{
std::cout<<"Location:func.cpp->func()"<<std::endl;
}
//main.cpp
#include <iostream>
void func();//or extern void func();
int main()
{
func();
return 0;
}
編譯:g++ -g func.cpp main.cpp -o run
在func.cpp中定義了函數(shù)func(),要在main.cpp中使用這個函數(shù)的話,必須在main.cpp中先聲明這個函數(shù)。注意這里func.cpp和main.cpp是兩個獨立的編譯單元,通過在main.cpp中聲明函數(shù),來實現(xiàn)函數(shù)在文件間的共享。在編譯時必須同時包含這兩個cpp文件。
其次,可以使用static修飾函數(shù),來限制函數(shù)的鏈接性。
如果在上面的函數(shù)中將func.cpp中的func()函數(shù)用static來修飾,同時給出函數(shù)的實現(xiàn),即
static void func()
{
std::cout<<"Location:func.cpp->func()"<<endl;
}
1
2
3
4
那么即使在main.cpp中聲明函數(shù)也是無法進行編譯的,可能編譯錯誤提示如下:
/tmp/ccoMrixR.o: In function `main':
/home/project/extern/main.cpp:7: undefined reference to `func()'
collect2: ld returned 1 exit status
最后,我的一位同事給我拋出了這樣的一個“疑問”:如果將func()函數(shù)放在func.h中,然后在mian.cpp中包含著func.h,那么無論是否用static修飾函數(shù)都是可行的,這不是有悖于上面的闡述嗎?或者說如果這樣可行的話,那么函數(shù)鏈接性的意義在哪兒了?
//func.h
#include <iostream>
void func()
{
std::cout<<"Location:func.cpp->func()"<<std::endl;
}
//main.cpp
#include <iostream>
#include "func.h"
void func();
int main()
{
func();
return 0;
}
實際上這并不矛盾,因為當(dāng)包含這個函數(shù)進行編譯時,func.h和main.cpp并不是兩個不同的編譯單元,當(dāng)然所謂函數(shù)鏈接性也就無從談起。當(dāng)#include “func.h”,編譯main.cpp時,會將頭文件進行展開,他們是同一個編譯單元。
————————————————
原文鏈接:https://blog.csdn.net/cjf_wei/article/details/66500244
*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。