博客專欄

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

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

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

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)系工作人員刪除。



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

相關(guān)推薦

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

關(guān)閉