2006年7月5日 星期三

思考泛型設計的學習 2

0

上次說到在泛型庫上,目前就是介意必須提供整個源碼,而無法只提供共享庫,其主要原因來做個簡單的說明吧!先看以下程式碼
//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, std::allocator > >(std::basic_string, std::allocator >& )'
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 意見:

 
Design by ThemeShift | Bloggerized by Lasantha - Free Blogger Templates | Best Web Hosting