博客專欄

EEPW首頁(yè) > 博客 > C++中關(guān)于函數(shù)的extern鏈接性以及extern關(guān)鍵字

C++中關(guān)于函數(shù)的extern鏈接性以及extern關(guān)鍵字

發(fā)布人:電子禪石 時(shí)間:2020-02-20 來(lái)源:工程師 發(fā)布文章

C++中extern關(guān)鍵字主要有三種作用,即聲明變量的鏈接性、函數(shù)的鏈接性、以及語(yǔ)言的鏈接性。所謂的鏈接性(linkage)是指名稱如何在不同的編譯單元間共享。與其相應(yīng)的是作用域(scope),它描述的是名稱在一個(gè)編譯單元的多大范圍內(nèi)可見。

變量的鏈接性:由于C++中變量具有單定義規(guī)則(one definiton rule)(只能被定義一次),那么在同一個(gè)工程的其他文件中,如果要想使用一個(gè)已經(jīng)定義的變量,只能使用聲明(declaration)。一個(gè)全局變量的默認(rèn)鏈接性是只在本文件可見,在另外一個(gè)文件中可以使用extern來(lái)聲明這個(gè)變量,表示該變量已經(jīng)在它處定義,從而使得該變量在“變量聲明”所在的文件同樣可見,達(dá)到共享的目的。

函數(shù)的鏈接性:默認(rèn)情況下函數(shù)的鏈接性是外部的,即可以在文件間共享。可以使用extern來(lái)指出這一點(diǎn),即該函數(shù)是在另外一個(gè)文件中定義的,不過(guò)這是可選的。但是如果用static來(lái)修飾函數(shù)的話,那么其鏈接性就是內(nèi)部的。
如果用static修飾函數(shù)的鏈接性,必須同時(shí)給出函數(shù)原型以及定義。

static int private(double x);
...
static int private(double x)
{
    ...
}

  

語(yǔ)言的鏈接性:在C語(yǔ)言中函數(shù)是不能重載的,因此在編譯后,一個(gè)函數(shù)名對(duì)應(yīng)于一個(gè)翻譯后的符號(hào)名,例如 test(int),對(duì)應(yīng)于_test。但是C++是可以重載的,因此函數(shù)經(jīng)編譯器翻譯后的名稱會(huì)有所不同。例如會(huì)將test(int),對(duì)應(yīng)于_test_i。但是可以使用extern “C”來(lái)告訴編譯器不要按照C++默認(rèn)的方式翻譯,而使用類似于C的方式翻譯。

下面通過(guò)示例來(lái)具體說(shuō)下函數(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中使用這個(gè)函數(shù)的話,必須在main.cpp中先聲明這個(gè)函數(shù)。注意這里func.cpp和main.cpp是兩個(gè)獨(dú)立的編譯單元,通過(guò)在main.cpp中聲明函數(shù),來(lái)實(shí)現(xiàn)函數(shù)在文件間的共享。在編譯時(shí)必須同時(shí)包含這兩個(gè)cpp文件。

其次,可以使用static修飾函數(shù),來(lái)限制函數(shù)的鏈接性。
如果在上面的函數(shù)中將func.cpp中的func()函數(shù)用static來(lái)修飾,同時(shí)給出函數(shù)的實(shí)現(xiàn),即

static void func()
{
    std::cout<<"Location:func.cpp->func()"<<endl;
}

    1
    2
    3
    4

那么即使在main.cpp中聲明函數(shù)也是無(wú)法進(jìn)行編譯的,可能編譯錯(cuò)誤提示如下:

/tmp/ccoMrixR.o: In function `main':
/home/project/extern/main.cpp:7: undefined reference to `func()'
collect2: ld returned 1 exit status


最后,我的一位同事給我拋出了這樣的一個(gè)“疑問(wèn)”:如果將func()函數(shù)放在func.h中,然后在mian.cpp中包含著func.h,那么無(wú)論是否用static修飾函數(shù)都是可行的,這不是有悖于上面的闡述嗎?或者說(shuō)如果這樣可行的話,那么函數(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;
}

 
 
實(shí)際上這并不矛盾,因?yàn)楫?dāng)包含這個(gè)函數(shù)進(jìn)行編譯時(shí),func.h和main.cpp并不是兩個(gè)不同的編譯單元,當(dāng)然所謂函數(shù)鏈接性也就無(wú)從談起。當(dāng)#include “func.h”,編譯main.cpp時(shí),會(huì)將頭文件進(jìn)行展開,他們是同一個(gè)編譯單元。
————————————————

原文鏈接:https://blog.csdn.net/cjf_wei/article/details/66500244

*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。



關(guān)鍵詞: C++

相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉