MyMSDN記錄開(kāi)發(fā)新知道
如圖所示的代碼出現(xiàn)了如圖所示的錯(cuò)誤,誰(shuí)能解釋一下是為什么呢?
雖然在最后include進(jìn)了cpp文件,而且這種做法也在C++ Primer中也是正確的(難道是標(biāo)準(zhǔn)和現(xiàn)實(shí)的差距?)。將代碼稍微變動(dòng),并將cpp部分的內(nèi)容移到.h文件中的include位置即可正確編譯。
posted on 2009-02-22 06:05 volnet 閱讀(4331) 評(píng)論(20) 編輯 收藏 引用
我記著這是個(gè)老問(wèn)題了,的確不少的參考書(shū)中這么說(shuō)過(guò),但是要注意兩點(diǎn): 1.這樣的分離只是文件層面的分離,并非是傳統(tǒng)的模塊之間只見(jiàn)接口,不見(jiàn)實(shí)現(xiàn)的分離,做為沒(méi)用動(dòng)態(tài)特性的靜態(tài)語(yǔ)言,C++把模板的實(shí)現(xiàn)封裝成二進(jìn)制是不可能的,這種編程技巧只是為了讓代碼瀏覽起來(lái)感覺(jué)更規(guī)范. 2.不同的編譯器對(duì)模板的實(shí)現(xiàn)還沒(méi)有完全按照標(biāo)準(zhǔn)來(lái)支持,所以產(chǎn)生錯(cuò)誤了不奇怪. 回復(fù) 更多評(píng)論
是"沒(méi)有動(dòng)態(tài)特性"的,打錯(cuò)了,不好意思 回復(fù) 更多評(píng)論
在源代碼級(jí)別,模板是可以有一定程度的分離的.我舉個(gè)例子//lib.htemplate <class T> const T& return_itself(const T& val);//lib.cpptemplate <class T> const T& return_itself(const T& val){ return val; }void instantiate_return_itself(){ //this is not executing factually. return_itself((int)0);}//app.cpp#include "lib.h"int main(){ return_itself((int)0); // OK return_itself(0.0f); // no compiler error happens but some link errors} 回復(fù) 更多評(píng)論
樓上說(shuō)的是模板函數(shù),的確可以分離,但模板類就不太容易了 回復(fù) 更多評(píng)論
樓主,你的問(wèn)題其實(shí)很簡(jiǎn)單。 你是不是把foo.cpp也放進(jìn)Visual C++的項(xiàng)目里了?如果是的話,這樣會(huì)導(dǎo)致foo.cpp的編譯,這個(gè)編譯會(huì)導(dǎo)致T Foo<T>::GetInstance(void)被編譯實(shí)現(xiàn)。當(dāng)繼續(xù)編譯main.cpp的時(shí)候,就會(huì)報(bào)告,T Foo<T>::GetInstance(void)已經(jīng)有一個(gè)實(shí)例了。 解決辦法很簡(jiǎn)單,把foo.cpp移出工程就可以了。只要物理上foo.h的同目錄存在foo.cpp這個(gè)文件就可以了。因?yàn)閒oo.cpp根本沒(méi)必要去編譯。甚至我都不建議你稱其為foo.cpp,不如叫什么foo_impl.hpp之類的文件名更合理些,這樣即使這個(gè)文件在工程里面也不回導(dǎo)致被編譯。 回復(fù) 更多評(píng)論
Foo.cpp里改成:#ifndef FOO_H_#include "foo.h"template<typename T> T Foo<T>::GetInstance() { return instance;}#endif可以試一下... 回復(fù) 更多評(píng)論
Dancefire 的答案是對(duì)的,如果你自己寫(xiě)makefile的話,肯定不能把foo.cpp編譯成foo.obj。 書(shū)上沒(méi)有說(shuō)這一點(diǎn),但是你的IDE自動(dòng)幫你makefile了,所以有些時(shí)候,自動(dòng)化也有不好的地方呀。 回復(fù) 更多評(píng)論
@Dancefire 的確,把foo.cpp移出項(xiàng)目外的話就可以順利編譯并執(zhí)行了! 但是在你的回答中,為什么會(huì)提到“當(dāng)繼續(xù)編譯main.cpp的時(shí)候……”,這是為什么呢?為什么非模板類型就可以? 回復(fù) 更多評(píng)論
非模板類型的應(yīng)該也是不可以的。還有就是,不僅僅是模板函數(shù),模板類一樣可以。 回復(fù) 更多評(píng)論
@空明流轉(zhuǎn) 我說(shuō)的可以是指在h中聲明,在cpp中定義,這顯然是可以的(也是標(biāo)準(zhǔn)的做法) 模板函數(shù)和模板類的確都存在如本文所述的問(wèn)題,并且用Dancefire的方法,或者使用全部寫(xiě)在.h文件中的方式,都是可以的。 回復(fù) 更多評(píng)論
@volnet呵呵,非模板類型的函數(shù)定義我們也不會(huì)需要在foo.h中include foo.cpp啊:)在樓主的例子里面為了能夠讓定義和聲明分開(kāi),將聲明放到了foo.h中,而定義放到了foo.cpp中,這和非模板類型的函數(shù)是一樣的。但是可惜這么做是無(wú)法通過(guò)的,因?yàn)槟0孱愋秃瘮?shù)不能夠(由于沒(méi)有export支持)單獨(dú)編譯。為了讓編譯通過(guò),樓主將foo.cpp給include進(jìn)了foo.h,這樣實(shí)際上是將兩個(gè)文件整合成一個(gè)文件了。這樣編譯就沒(méi)有問(wèn)題了,但是得小心需要把foo.cpp分離出項(xiàng)目,因?yàn)樗豢梢员痪幾g;或者將其擴(kuò)展名從.cpp改為.hpp。實(shí)在是不推薦樓主這么分開(kāi)的寫(xiě),說(shuō)實(shí)話這算不上是什么標(biāo)準(zhǔn)的做法,而且這樣并沒(méi)有太大的意義。如果非要分開(kāi),可以將定義后綴到聲明后面,在一個(gè)文件里。但是分開(kāi)確實(shí)沒(méi)太大意義。可以研讀一下boost里面的做法。 回復(fù) 更多評(píng)論
@Dancefire 原來(lái)你們說(shuō)的是include foo.cpp 分開(kāi)有一個(gè)好處就是可以成套地替換吧,雖然通常我們不這么做,但是卻從語(yǔ)法上支持了這么做。如果可以當(dāng)然好了,不行的話肯定是沒(méi)辦法的。 回復(fù) 更多評(píng)論
@Dancefire boost在C++中的地位是什么呢?一個(gè)工業(yè)庫(kù)?一個(gè)泛型標(biāo)準(zhǔn)?一個(gè)開(kāi)源范例?它對(duì)C++學(xué)習(xí)有什么好處呢? 回復(fù) 更多評(píng)論
@volnetBoost可以稱其為是一套準(zhǔn)標(biāo)準(zhǔn)庫(kù)。它項(xiàng)目建立的目的之一就是為未來(lái)的C++標(biāo)準(zhǔn)庫(kù)提供候選方案,目前已經(jīng)有將近十個(gè)Boost庫(kù)成功的成為了C++標(biāo)準(zhǔn)預(yù)案。它的優(yōu)勢(shì)很多,首先是代碼使用現(xiàn)代C++的語(yǔ)法,因此namespace, 異常, 模板之類的C++特性會(huì)被充分挖掘利用,代碼從設(shè)計(jì)、實(shí)現(xiàn)到文檔都具有了相當(dāng)高的水準(zhǔn)。另外,由于它使用的是標(biāo)準(zhǔn)C++語(yǔ)法編寫(xiě),因此它的可移植性非常的好。當(dāng)然,針對(duì)一些存在問(wèn)題的編譯器,它也會(huì)進(jìn)行相應(yīng)的調(diào)整以盡量支持。Boost這種優(yōu)良的庫(kù),涵蓋的領(lǐng)域很廣,可以說(shuō)是標(biāo)準(zhǔn)庫(kù)很好的補(bǔ)充。另外絕大多數(shù)Boost庫(kù)都不需要編譯鏈接,大部分的Boost庫(kù)僅僅include頭文件即可工作。我看到國(guó)內(nèi)很多人提到Boost的時(shí)候說(shuō)它比較難以編譯安裝云云。其實(shí)沒(méi)必要編譯,絕大多數(shù)的庫(kù)僅僅是由頭文件組成的,只要include進(jìn)來(lái)就可以用了。Boost是C++強(qiáng)有力的工具,學(xué)習(xí)C++,除了標(biāo)準(zhǔn)語(yǔ)法和STL外,Boost是必須熟悉的,否則,工程上很有可能會(huì)做一些Boost已經(jīng)實(shí)現(xiàn)很久的東西,除了重復(fù)開(kāi)發(fā)外,而且你的代碼的質(zhì)量和可持續(xù)性比Boost差很遠(yuǎn),造成項(xiàng)目質(zhì)量的下降。 回復(fù) 更多評(píng)論
@Dancefire 謝謝你對(duì)Boost做了詳細(xì)的介紹。 那么,學(xué)習(xí)Boost庫(kù)需要有哪些準(zhǔn)備工作?(假設(shè)從初學(xué)者開(kāi)始)學(xué)習(xí)Boost庫(kù)又有哪些方法或者經(jīng)典的做法呢?(比如什么書(shū),或者什么文檔) 回復(fù) 更多評(píng)論
foo.h里面最下面倒數(shù)第二行 的#include 回復(fù) 更多評(píng)論
@maosher 怎么了? 回復(fù) 更多評(píng)論
template特化是鏈接期不能解決的問(wèn)題,因此必須放進(jìn).h,不要使用別扭的技巧來(lái)分離。其實(shí)直接寫(xiě)在一個(gè)class{}里面反而漂亮得多。 回復(fù) 更多評(píng)論
簡(jiǎn)單的問(wèn)題。把foo.cpp中#include "foo.h"那行刪除掉應(yīng)該就沒(méi)問(wèn)題了。 回復(fù) 更多評(píng)論
.cpp 的模板前面加個(gè) export試試 回復(fù) 更多評(píng)論
Powered by: C++博客 Copyright © volnet