我有一个非常奇怪的错误:我有一对包含一些函数和常量的.h和.cpp文件。当我尝试编译它时,g ++对函数说“未定义引用”。函数原型和定义似乎是相同的。除了必要的行之外,我已经对所有内容进行了评论,并且g ++仍然抱怨它。
我的节目目前(在评论完所有内容后):
的main.cpp
#include "a.h"
int main(){
makehex(10);
return 0;
}
A.H
#include <iostream>
#include <sstream>
#ifndef __A___
static const std::string b = "01";
static const std::string d = b + "23456789";
static const std::string h = d + "abcdef";
template <typename T> std::string makehex(T value, unsigned int size = 2 * sizeof(T));
#endif
a.cpp
#include "a.h"
template <typename T> std::string makehex(T value, unsigned int size){
// Changes a value to its hexadecimal string
if (!size){
std::stringstream out;
out << std::hex << value;
return out.str();
}
std::string out(size, '0');
while (value && size){
out[--size] = h[value & 15];
value >>= 4;
}
return out;
}
只有一个功能。我不明白这是怎么回事。
我正在使用g++ -std=c++11 main.cpp a.cpp
进行编译并获取错误:
main.cpp:(.text+0x1a): undefined reference to `std::string makehex<int>(int, unsigned int)'
collect2: error: ld returned 1 exit status
是不是因为模板?如果是这样,我该如何解决?
答案 0 :(得分:2)
您需要了解模板本身不是代码,但它告诉编译器如何生成程序其他部分可以使用的代码。为了使编译器能够自动执行此操作,必须在实例化时看到该模板的定义。
但是在您现有的设置中,makehex<T>()
中只能看到main.cpp
的声明。 makehex<T>()
的实际定义在a.cpp
中被遗忘,主要在编译期间不知道(它在不同的翻译单元中)。对此的简单解决方法是移动{{1}的实现从a.cpp到啊
答案 1 :(得分:1)
常见模板错误。编译器需要在编译时知道模板的定义:因此,模板函数的定义必须在头文件中。
答案 2 :(得分:1)
只有在实际实例化模板时才会发出模板函数。您正在尝试使用调用makehex(10)
。
您在main.cpp文件中包含了“a.h”,因此在编译main.cpp时,您可以访问该函数的声明。但是,编译器无法访问定义,因为它位于未包含的其他文件(a.cpp)中。
短期修复是在main.cpp中#include "a.cpp"
。但是,长期修复不是要有模板函数定义的.cpp文件 - 将它全部放在标题(.h)文件中。 (这不适用于普通的函数/类等)。