2011-09-03 129 views
1

我試圖做folllowing: 類定義.h文件:模板規範問題

template<int Size> 
class Sculptor 
{ 
public: 
    Sculptor(); 

    ~Sculptor(void) ; 

    void Sculp(SculptData* sculpData); 

    void ToShape(Shape* shape); 

    int CalculateMesh(); 

    unsigned char sculpture[Size][Size][Size]; 
} 

類定義的cpp文件來塑造功能(所有其他人都一樣):

template<int Size> 
void Sculptor<Size>::ToShape(Shape* shape){} 

使用:

Sculptor<16> sclupt; 

Shape shape; 

SculptData* data = CreateCircle(); 


sclupt.Sculp(data); 
sclupt.CalculateMesh(); 
sclupt.ToShape(&shape); 

我得到以下錯誤 enter image description here

你能告訴我問題的根源嗎?

+2

是這樣的情況:http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13? – Flexo

+0

從cpp文件編輯添加的例子 –

+0

準確地說 - 它可能在不同的cpp文件中,所以從不在輸出中實例化。 – Flexo

回答

3

請記住,模板類的實現必須在使用它的編譯單元中可見。特別是,您可能不會將實現放在單獨的位置。cpp文件(這是非模板類的常見做法),而應將其放置在聲明模板的頭文件中。

+0

即使代碼編譯成一個obj文件? –

+2

@Sergey Kucher:是的。類模板不能編譯到實際的機器代碼,因爲類型還不知道。 –

3

99%的時間a LNK2019意味着你忘記了實際完全定義了你在某處使用過的函數或類的主體。 ToShape(), Sculp()CalculateMesh()的執行哪裏?那麼構造函數和析構函數 呢?

看來您正在將實現置於.cpp文件中。儘管可以理解應該將接口與實現分離,但類模板與非模板完全不同。

編譯器實際上並沒有爲模板生成任何機器代碼,因爲尚未定義所有模板參數。例如,在不知道成員數組有多大的情況下,您無法生成Sculptor的機器碼。編譯器事先並不知道Size == 16何時編譯器開始解析模板定義。所以你得到鏈接器錯誤,因爲鏈接器找不到它的機器代碼;它不存在!

對於模板類,你會通常把實施模板類聲明本身 ,所以你可能真的是缺少這些功能定義 這樣的:

template<int Size> 
class Sculptor 
{ 
public: 
    Sculptor() 
    { 
     // implementation 
    } 

    // and so on... 

在Boost庫的模板和C++標準庫是這樣定義的。


一個側面說明:與Size == 16,要創建與4096 unsigned char,它出現一個3x3的陣列。雖然這本身並不成問題,但當堆棧中至少有4096個unsigned char s時,堆棧溢出相當容易。

+0

cpp文件中的實現,現在正在編輯 –

+2

那最有可能是你的問題了。一般而言,模板函數需要使用它們的代碼(完整定義而不僅僅是聲明)可見。這通常意味着您必須將模板函數的主體放在.h文件中,並將它們包含在關於您的邊界 – jcoder

+0

的任何地方。注意什麼是我的上限?實際上,當大小爲1024時,我得到堆棧溢出 –

1

您忘了編寫ToShape,Sculp,CalculateMesh,構造函數和析構函數的代碼。實現它們或添加一個虛擬實現,程序將鏈接。

另外:

unsigned char array sculpture[Size][Size][Size]; 

是無效的C++(除非數組是一些無效定義),你的意思是這樣呢?

unsigned char sculpture[Size][Size][Size]; 
+0

:) cpp文件中的實現 –

0

模板必須在所有使用它們的翻譯單元中完全定義 - 不能鏈接它們。這意味着編譯器無法找到正在調用的函數的主體。