__declspec(selectany)的作用
__declspec是一個(gè)Microsoft Visual C++特定的編譯器屬性開關(guān)。括號(hào)中指
明的是哪一個(gè)屬性生效。關(guān)于__declspec的其他屬性可以百度“__declspec msdn”
查看微軟的官方幫助。也可以參看博客中轉(zhuǎn)載的文章。
言歸正傳。__declspec(selectany)在MSDN中的說明是這樣的:
Tells the?compiler?that the declared global data item (variable?or object) is a pick-any?
COMDAT (a packaged function). At link time, if multiple?a?definitions?of?COMDAT are?
seen, the linker picks one and?discards?the rest. Selectany?can be used in initializing?
global data?defined?by headers,when the same header appears in more than one?
source file.?
?
簡單翻譯一下:告訴編譯器定義的全局?jǐn)?shù)據(jù)項(xiàng)(變量或?qū)ο?#xff09;這是一套能被任
意挑選的COMDAT(一套函數(shù))。在鏈接時(shí),如果多個(gè)COMDAT的定義被找到,
鏈接器將挑選一個(gè)并剔除其他的多余的。Selectany可以被用于當(dāng)定義有初始化全局
變量數(shù)據(jù)的頭文件被應(yīng)用于多于一個(gè)的源文件時(shí)。
我這樣的翻譯還是挺虛的,直白了說:當(dāng)在頭文件定義全局變量,并且這個(gè)頭
文件被include多次時(shí)可以用這個(gè)開關(guān)剔除由于多次include而產(chǎn)生的重定義。
看起來這個(gè)開關(guān)很有用,但這個(gè)開關(guān)我們用得并不多。很明顯,根據(jù)msdn的解釋,
對(duì)于定義常量這個(gè)開關(guān)是用不上的了,而全局變量一般來說定義在cpp中,那么這個(gè)
開關(guān)有什么用呢?
?
這正是這篇文章要討論的主題。
(1)基于程序結(jié)構(gòu)的整齊,統(tǒng)一將全局變量定義在一個(gè)全部cpp都引用的頭文件,
這樣也就避免了在每個(gè)cpp中用extren導(dǎo)入外部變量。當(dāng)然,這隨你的習(xí)慣了。
(2)模板的設(shè)計(jì)。類模板,函數(shù)模板,這些肯定不會(huì)只被一個(gè)cpp所使用,按照一般
的習(xí)慣都是寫在頭文件的。但是對(duì)于模板,其實(shí)現(xiàn)是在編譯期完成的,那就要求必須
在編譯的時(shí)候同時(shí)找到模板的定義和實(shí)現(xiàn),也就是意味著不可能像以前的習(xí)慣一樣,
將類的聲明放在頭文件,將實(shí)現(xiàn)放在cpp中。那么模板類的靜態(tài)成員變量怎么辦呢?
類的靜態(tài)成員必須在類外部初始化,如果是全寫在頭文件,當(dāng)頭文件include多于一次
的時(shí)候就會(huì)出現(xiàn)類的靜態(tài)變量重定義的問題,可以做一個(gè)簡單的實(shí)驗(yàn):
sy.h:
class A { public:static int u; }; int A::u=1;
1.cpp:
2.cpp:
就這樣三個(gè)文件,在一個(gè)工程中,組建一下(編譯沒問題,問題出在鏈接的時(shí)
候),就會(huì)出現(xiàn):
2.obj : error LNK2005: "public: static int A::u" (?u@A@@2HA) already defined in sy.obj
Debug/sy.exe : fatal error LNK1169: one or more multiply defined symbols found
這時(shí)候就只能使用__declspec(selectany)去解決了,將sy.h的第六行改為:
?
__declspec(selectany) int A::u=1;
即可解決問題。
下面來討論一個(gè)問題,那么看下面的代碼:
key.h:
const char *Function[28]= {"menu","exit","rad","sin","cos","tan","sec","csc","cot","asin","acos","atan","acsc","asec","acot","sh","ch","th","ash","ach","ath","log","lg","ln","sum","mul","A","C" };這個(gè)頭文件被include了多次。我的原意的是希望建立一個(gè)字符串的數(shù)
組常量,上面說了定義常量并不需要用這個(gè)開關(guān),但為什么還是會(huì)出
現(xiàn)重定義的問題呢?而且確實(shí)能用__declspec(selectany)去解決。
實(shí)際上這個(gè)可以不用__declspec(selectany)去解決,寫成這樣即可:
const char* const Function[28]= {"menu","exit","rad","sin","cos","tan","sec","csc","cot","asin","acos","atan","acsc","asec","acot","sh","ch","th","ash","ach","ath","log","lg","ln","sum","mul","A","C" };如果在看了我的原意之后并沒有發(fā)現(xiàn)一開始給的代碼有什么問題,請想
一下用__declspec(selectany)去解決雖然沒有問題,但符合我的原意嗎?
這樣Function的內(nèi)容到底是變量還是常量?
總結(jié)
以上是生活随笔為你收集整理的__declspec(selectany)的作用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 换种思路去理解设计模式
- 下一篇: vector作为参数传递到dll问题