模板规范问题

时间:2011-09-03 12:03:45

标签: c++ templates

我正在努力做到以下几点: 类定义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

你能告诉我问题的根源吗?

4 个答案:

答案 0 :(得分:3)

99%的时间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 s的3x3阵列。虽然这本身并不是问题,但当单个Sculptor在堆栈上占用至少4096 unsigned char时,很容易溢出堆栈。

答案 1 :(得分:3)

请记住,模板类的实现必须在使用它的编译单元中可见。特别是,您可能不会将实现放入单独的.cpp文件中(这是非模板类的常见做法),而是应将其放在声明模板的头文件中。

答案 2 :(得分:1)

您忘记编写ToShape,Sculp,CalculateMesh,构造函数和析构函数的代码。实现它们或添加一个虚拟实现,程序将链接。

此外:

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

是无效的C ++(除非数组是一些无效的定义),你的意思是这个吗?

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

答案 3 :(得分:0)

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