久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

鏈接過程重復定義

 昵稱16235376 2014-06-19
首先,,我們來了解下定義:

內部連接:如果一個名稱對編譯單元(.cpp)來說是局部的,,在鏈接的時候其他的編譯單元無法鏈接到它,。

外部連接:如果一個名稱對編譯單元來說不是局部的,,而在鏈接的時候其他的編譯單元可以訪問它,,也就是說它可以和別的編譯單元交互,。

 

通過對LIB與DLL的講解,我們可以更方便的理解內部連接與外部連接,。

我們了解了一個編譯單元(.cpp)編譯成obj文件后,,至少還會有未解決符號表、導出符號表,、地址重定向表,。而如果這個名稱是內部連接的話,,那在導出符號表中不存儲它的入口。也就是別的obj文件無法鏈接到這個名稱,。而外部連接剛好相反,,在導出的符號表中有它入口。

 

以下情況有內部連接:
a)所有的聲明
b)名字空間(包括全局名字空間)中的靜態(tài)自由函數,、靜態(tài)友元函數,、靜態(tài)變量的定義
c)enum定義
d)inline函數定義(包括自由函數和非自由函數)
e)類的定義
f)名字空間中const常量定義
g)union的定義

以下情況是外部連接:

a)非static全局變量與全局函數

b)類非inline函數總有外部連接。包括類成員函數和類靜態(tài)成員函數
c)類靜態(tài)成員變量總有外部連接
d)名字空間(包括全局名字空間)中非靜態(tài)自由函數,、非靜態(tài)友元函數及非靜態(tài)變量

好了,,我們通過程序來深刻的理解吧:

假設有3文件: 

TestBase.h:                       TestRun.cpp                          TestError.cpp

int a;                                    #include "TestBase.h"            #include "TestBase.h"

當然還有一個包含main()方法的Test.cpp輸出的文件。

#include "TestBase.h"  

extern int a;

void print()

{

    cout << a<<endl;

}

分別編譯TestRun與TestError我相信大家都能通過編譯,,但是你鏈接的時候肯定會出錯的,,提示的信息有一句為:Debug/Test.exe : fatal error LNK1169: one or more multiply defined symbols found(一個或多個定義符號被發(fā)現)。因為非static的全局變量是外部連接的,,其實也就是說TestRun.obj與TestError .obj的導出符號表中都對a導出了信息入口(別問我為什么導出了它,,因為編譯器默認對非static全局變量都導出了,想知道怎么實現的,,可以去找Microsoft),。而當我的Test.cpp中要用到a時我到底是用TestRun.obj還是TestError .obj中導出符號表中的a呢?所以鏈接肯定會出錯的,。

我們在嘗試著把TestBase.h中的全局變量a改了static,。馬上能編譯與鏈接成功,并輸出0,,其實是因為static全部變量是內部連接的,,obj文件的導出符號表中沒有提供a符號的入口。而Test.cpp用到的是自己在編譯的時候得到的a的信息,,也就是TestBase.h文件中a的默認值0.

函數的性質也是一樣的,,所以大家只需要知道你聲明或定義的名稱是內部連接還是外部連接,如TestBase.h中的非全局變量a是外部連接,。你就會明白語法其實也就那么回事了。

讓我們在來了解class里的static變量和非static函數是什么樣子的,。

class是內部連接的,,這就是為什么可以有多個cpp文件能包含它的原因了,但是如果我在class里寫了個static變量了,,那這個變量就是外部連接了,。而內中的非static函數了是外部連接。所以針對class我總結了下3點必須:

(1),。類中的static變量請不要在聲明類中定義,。一般我們類的聲明是寫到.h文件中,,而實現寫到對應的cpp文件中的,理由看程序,。

還是剛才3個文件:

TestBase.h:                                        TestRun.cpp                                       TestError.cpp

class A                                               #include "TestBase.h"                        #include "TestBase.h" 
{                                                             int A::getA()
public:                                                  {
     void setA( int a );                            return m_a;
                 int getA();                            }
                 inline int getB();                  void A::setA( int a )
private:                                                  {
                int m_a;                                              m_a = a;
                static int m_b;                        }
};

int A::m_b = 5;

編譯都成功后,,鏈接會出現如下信息:

TestError.obj : error LNK2005: "private: static int A::m_b" (?m_b@A@@0HA) already defined in Test.obj
TestRun.obj : error LNK2005: "private: static int A::m_b" (?m_b@A@@0HA) already defined in Test.obj
Debug/Test.exe : fatal error LNK1169: one or more multiply defined symbols found

也就是說類中的static變量m_b為外部連接,理由同上面寫的全局變量a一樣,。解決辦法是把int A::m_b = 5;寫到類的實現文件TestRun.cpp 中,,這樣就只有TestRun.obj文件的導出符號表中提供了m_b,而其他的obj文件如果需要的話,,那這只能在它的未解決符號表中存在了,,它自然只能在TestRun.obj文件中找到m_b的入口,這樣就無任何沖突了,。所以類中的static變量請一定不要在聲明類中定義,。

(2)。內中的非static函數請一定也不要在聲明類實現,,除非你的聲明和實現是寫到一起的,。

TestBase.h:                                           TestRun.cpp                                       TestError.cpp

class A                                                  #include "TestBase.h"                          #include "TestBase.h" 
{                                                          int A::getA()
public:                                                  {
     void setA( int a );                        return m_a;   
                 int getA();                            }
                 inline int getB();                  int  A::m_b = 6;
private:                                                  
                int m_a;         

                 static int m_b;                                                                
};    

void    A::setA( int a )

{

    m_a = a;

}          

編譯通過,鏈接后肯定不能通過,,原因都一樣,,就是因為類中的非static函數是外部鏈接。而如果你把定義和聲明寫到一起,,那就沒問題,,但你應該知道這樣寫就是相當于出賣了自己,你把你的實現代碼都給了別人,。

(3)inline函數請一定要在類的聲明文件中實現,。大家應該看到類中的inline函數我沒有寫它的實現代碼,其實也就是為了這條定義一樣,。你可以查看VC提供的頭文件中inline的定義與實現都是寫在頭文件中的,。

所以那個inline函數你必須寫在TestBase.h內。        

inline int A::getB()
{
         return m_b; 
}            

為什么這樣呢,?因為inline函數是內部連接,,它不在導出符號表。假如你把inline int getB()的實現代碼寫在了 TestRun.cpp中,,那鏈接后的錯誤信息是:

Debug/Test.exe : fatal error LNK1120: 1 unresolved externals

也就是別的cpp文件就無法用到找到它了,。

好了,其實很多東西如果是在鏈接時候出錯了,,或者為什么語法這么實現的,,你可以從它是內部連接還是外部鏈接入手,你會發(fā)現很多規(guī)律以及規(guī)則的存在,這樣你的編寫的C++的代碼安全性一定會大大的提高,。相信我,!

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現有害或侵權內容,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多