static inline與內部、外部鏈接對象


一個由inline引起的討論

以下函數定義有問題么:

//function.h

Void hello(){

       Printf(“hello,world”);

}

 

一般人看起來肯定覺得不對,因為我們基本上只把函數定義放在cpp里面,然后定義一個.h聲明一下,在使用的地方include 一下這個.h就Ok了。可是為什么要這樣做呢?

換句話說,如果我們按上面的方法定義hello(在一個.h里面定義),然后在兩個文件a.cpp和b.cpp里面同時include了它,然后我們編譯的時候沒錯,鏈接的時候告訴我們hello被定義了兩次,這是為什么呢?

我們要知道,你include一個文件的時候相當於把那個文件的內容copy到被include的地方了。所以如果我們有兩個文件a.cpp和b.cpp,我們都include了那個hello.h,然后編譯,就相當於在a.cpp和b.cpp里面都定義了一個hello,然后鏈接當然出錯了。這是問題的本質

 

然而,如果把hello的前面加一個inline,也就是說,改成

//function.h

Inline Void hello(){

       Printf(“hello,world”);

}

然后再定義a.cpp和b.cpp,同時incldue hello.h,編譯和鏈接都能正常。這又是為什么呢?只不過我們加了一個inline而已。

問題是的本質是inline表明一個函數是內部鏈接對象,所謂內部鏈接對象。為了說清楚內部鏈接對象,我不得不講一個東西。

編譯單元:

       在C或者CPP里面,一個編譯單元指的是一個可以被編譯的文件,在C或者CPP里面,只有.C和.CPP才能被編譯的,其它的任何擴展名的文件都不能被編譯,比如.h就不能被編譯。一個可以被編譯的文件就是一個編譯單元。所謂內部鏈接對象,指的是一個同樣的名字,如果出現在兩個編譯單元里面,它們卻算不同的東西,則是內部鏈接對象,否則,如果出現在不同的編譯單元的同樣的名字算同樣的東西,同,就是外部鏈接對象。

       上面的問題加了inline之后就解決了是因為inline函數是內部鏈接對象,不加inline則是外部鏈接對象。

       同樣的問題是static,函數加了static的則是內部鏈接,不加就是外部鏈接。對於類的定義也一樣,如果一個類的一個函數跟類的實體一起定義的,就是內部鏈接,否則算外部鏈接。

       比如:

//tt.h

#include<iostream>

using namespacestd;

 

class TT{

public:

       TT();

public:

       void hello();

};

 

TT::TT(){

       cout<<"TT"<<endl;

}

 

void TT::hello(){

       cout<<"Hello,worle"<<endl;

}

你這樣寫的話,這個類是完了,只能被include一次,否則鏈接出錯,因為它沒有加static,也沒加inline,也就是它是外部鏈接對象了。如果你把它改成

//TT.h

#include<iostream>

using namespacestd;

 

class TT{

public:

       TT(){

              cout<<"TT"<<endl;

       }

 

       void hello(){

              cout<<"Hello,worle"<<endl;

       }

};

那么這個類就能被使用了,因為跟類體一起定義的函數就是內部鏈接對象了。

當然,如果寫成前面這樣,就涉及到類的名字解析了,關於類的名字解析,我暫時不說,以后有機會再寫。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com