-1

我有一个非常奇怪的错误:我有一对 .h 和 .cpp 文件,其中包含一些函数和常量。当我尝试编译它时,g++ 对函数说“未定义的引用”。函数原型和定义似乎是一样的。除了必要的行之外,我已经将所有内容都注释掉了,而 g++ 仍然抱怨它。

我的程序目前是(在注释掉所有内容之后):

主文件

#include "a.h"

int main(){
    makehex(10);

    return 0;
}

#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;
}

只有1个功能。我不明白这怎么会出错。

我正在编译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

是因为模板吗?如果是这样,我该如何解决?

4

3 回答 3

2

常见的模板错误。编译器需要在编译时知道模板的定义:因此,模板函数的定义必须在头文件中。

于 2013-07-19T20:02:51.140 回答
2

您需要了解模板本身不是代码,而是告诉编译器如何生成程序的其他部分可以使用的代码。为了使编译器能够自动执行此操作,它必须在实例化时看到该模板的定义。

但是在您现有的设置makehex<T>()只有main.cpp. 的实际定义makehex<T>()被隐藏在a.cpp其中 main 在编译期间不知道(它在不同的翻译单元中)。对此的简单解决方法是将实现makehex<T>()从 a.cpp 移动到 ah

于 2013-07-19T20:04:44.133 回答
1

仅当您实际实例化模板时才会发出模板函数。您正在尝试在 main 函数中使用 call 执行此操作makehex(10)

您已在 main.cpp 文件中包含“ah”,因此在编译 main.cpp 时,您可以访问函数的声明。但是,编译器无法访问该定义,因为它位于另一个未包含的文件 (a.cpp) 中。

短期修复是#include "a.cpp"在 main.cpp 中。但是,长期的解决方法是不要将 .cpp 文件用于模板函数定义 - 将其全部放在头文件 (.h) 中。(这不适用于普通函数/类等)。

于 2013-07-19T20:05:29.427 回答