提问人:Daniel Sloof 提问时间:3/16/2009 最后编辑:Daniel Sloof 更新时间:3/30/2014 访问量:32466
C++ 模板,未定义的引用
C++ templates, undefined reference
问:
我有一个这样的函数声明:
template <typename T>
T read();
并按如下定义:
template <typename T>
T packetreader::read() {
offset += sizeof(T);
return *(T*)(buf+offset-sizeof(T));
}
但是,当我尝试在我的 main() 函数中使用它时:
packetreader reader;
reader.read<int>();
我从 g++ 收到以下错误:
g++ -o main main.o packet.o
main.o: In function `main':
main.cpp:(.text+0xcc): undefined reference to `int packetreader::read<int>()'
collect2: ld returned 1 exit status
make: *** [main] Error 1
谁能为我指出正确的方向?
答:
您需要使用关键字。但是,我认为 G++ 没有适当的支持,因此您需要在标头中包含模板函数的定义,以便翻译单元可以使用它。这是因为尚未创建模板的“版本”,而只创建了“版本”。export
<int>
<typename T>
一种简单的方法是使用 .cpp 文件。但是,这可能会导致问题,例如,当其他函数位于 .cpp 文件中时。它还可能会增加编译时间。#include
一种干净的方法是将模板函数移动到其自己的 .cpp 文件中,并将其包含在标头中或使用关键字并单独编译。export
有关为什么应尝试将模板函数定义放在其头文件中(并完全忽略导出
)的更多信息。
评论
模板函数的最佳做法是在头文件中定义它们。它们是在编译时创建的,因此编译器必须有定义才能这样做。
当模板得到更多支持时,情况并非如此,但现在它仍然几乎无法使用。export
评论
export
问题是函数模板不是函数。它是用于根据需要创建函数的模板。
因此,要使模板正常工作,编译器直观地需要两条信息:模板本身和应替换到其中的类型。
这与函数调用不同,编译器可以在知道函数存在后立即生成函数调用。它不需要知道函数的作用,只需要知道它的外观,或者它的签名是什么。void Frobnicate(int, float)
当您在不定义函数模板的情况下声明函数模板时,您只是告诉编译器存在这样的模板,而不是它的外观。这还不足以让编译器实例化它,它还必须能够看到完整的定义。通常的解决方案是将整个模板放在一个标题中,该标题可以包含在需要的地方。
他们的任何编译器支持模板是否单独编译?
据我所知,通常的做法是在头文件中声明和实现模板函数
评论