上次說到在泛型庫上,目前就是介意必須提供整個源碼,而無法只提供共享庫,其主要原因來做個簡單的說明吧!先看以下程式碼//file print.h
#include < iostream >
template < class T >
void print(T &data);//file print.cpp
#include "print.h"
#include < iostream >
using namespace std;
template < class T >
void print(T &data)
{
cout << data << endl;
}//file main.cpp
#include < string >
#include "print.h"
using namespace std;
int main()
{
string s("Hello" );
print(s);
}
在這邊,我們提供一個function templare,簡單的做個輸出,而.h檔裡面放置宣告,實做細節在.cpp檔中,而我們的主程式則是在main.cpp,在裡面宣告一個字串並初始為Hello,然後用print輸出他
接著我們試著編譯我們的程式$g++ main.cpp print.cpp
不過卻會發生一個錯誤/tmp/ccRlq0pc.o: In function `main':main.cpp: ( .text+0x54): undefined reference to `int print
collect2: ld 回傳 1
有趣的是錯誤的來源,居然是發生在ld,也就是linking的時候,程式的生成過程基本上是 源碼--編譯器--> 中介碼--組譯器--> 二進位碼 --連結器--> 執行檔
在連結時期會將所有相關的code組合起來,包括你所使用的其他函式庫,或分散其他部份的源碼所產生的二進位碼,而問題的發生便是連結時,找不到你所使用的print的定義,也就是寫在print.cpp裡的內容,或者說找不到其具現化(實體化)的部份
可以在main.cpp中加入一行#include "print.cpp"
或者將定義一併寫入print.h中,而後者被稱為置入式模型(inclusion model),如此linker便可依據源碼,具現化所有的物件,詳細討論可見C++ template一書第六章...
所以呢,如果真想只提供編譯後的共享連結庫,恐怕得在編譯器或連結器上採用不同的作法,不然就是以泛型庫做為基本組件,而在自己編寫的庫中都會被具現化,提供出來的則是包裝後的產品,不會在用到模板參數(template parameter)...不知道ACE裡面怎麼結合這些設計,再找時間來看看
0 意見:
張貼留言