对定义函数的未定义引用

时间:2013-07-19 20:01:17

标签: c++ g++ undefined-reference

我有一个非常奇怪的错误:我有一对包含一些函数和常量的.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

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

3 个答案:

答案 0 :(得分:2)

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

但是在您现有的设置中,makehex<T>()中只能看到main.cpp声明makehex<T>()的实际定义在a.cpp中被遗忘,主要在编译期间不知道(它在不同的翻译单元中)。对此的简单解决方法是移动{{1}的实现从a.cpp到啊

答案 1 :(得分:1)

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

答案 2 :(得分:1)

只有在实际实例化模板时才会发出模板函数。您正在尝试使用调用makehex(10)

在main函数中执行此操作

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

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