2011-09-03 77 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

模板必须在所有使用它们的翻译单元中完全定义 - 不能链接它们。这意味着编译器无法找到正在调用的函数的主体。