C ++ - LNK2019错误未解析的函数_main中引用的外部符号[模板类的构造函数和析构函数]

时间:2010-09-14 02:32:28

标签: c++ templates linker queue linker-errors

[[更新]] - >如果我在program.cpp中#include“Queue.cpp”,它就可以了。这不应该是必要的,对吗?

嘿所有 - 我正在使用Visual Studio 2010并且无法链接快速和脏的Queue实现。我从一个 Win32控制台应用程序开始,所有文件都存在于项目中。对于详细程度,这里是复制我的错误的完整代码。我意识到一些代码实际上可能是错误的。我还没有机会测试它,因为我还没有能够链接它。

Queue.hpp

#ifndef ERROR_CODE
#define ERROR_CODE
enum Error_Code
{
    Success,
    Underflow,
    Overflow
};
#endif // ERROR_CODE

#ifndef QUEUE
#define QUEUE
template<class T>
struct Queue_Node
{
    T data;
    Queue_Node *next;

    Queue_Node()
    {
        next = NULL;
    }
    Queue_Node(T pData)
    {
        data = pData;
        next = NULL;
    }
    Queue_Node(T pData, Queue_Node *pNext)
    {
        data = pData;
        next = pNext;
    }
};

template<class T>
class Queue
{
public:
    Queue();
    Error_Code Serve();
    Error_Code Append(T item);
    T Front();
    ~Queue();

private:
    void Rescursive_Destroy(Queue_Node<T> *entry);
    Queue_Node<T> *front, *rear;
};
#endif // QUEUE

Queue.cpp

#include "Queue.hpp"

template <class T>
Queue<T>::Queue()
{
    this->front = this->rear = NULL;
}

template<class T>
Error_Code Queue<T>::Serve()
{
    if(front == NULL)
        return Underflow;

    Queue_Node *temp = this->front;
    this->front = this->front->next;
    delete temp;
}

template<class T>
Error_Code Queue<T>::Append(T item)
{
    Queue_Node *temp = new Queue_Node(item);
    if(!temp)
        return Overflow;

    if(this->rear != NULL)
        this->rear->next = temp;
    this->rear = temp;

    return Success;
}

template<class T>
T Queue<T>::Front()
{
    if(this->front == NULL)
        return Underflow;
    return this->front->data;
}

template<class T>
Queue<T>::~Queue()
{
    this->Rescursive_Destroy(this->front);
}

template<class T>
void Queue<T>::Rescursive_Destroy(Queue_Node<T> *entry)
{
    if(entry != NULL)
    {
        this->Recursive_Destroy(entry->next);
        delete entry;
    }
}

program.cpp

#include "Queue.hpp"

int main()
{
    Queue<int> steve;
    return 0;
}

错误......

Error   1   error LNK2019: unresolved external symbol "public: __thiscall Queue<int>::~Queue<int>(void)" (??1?$Queue@H@@QAE@XZ) referenced in function _main    C:\[omitted]\Project2_2\Project2_2\program.obj  Project2_2
Error   2   error LNK2019: unresolved external symbol "public: __thiscall Queue<int>::Queue<int>(void)" (??0?$Queue@H@@QAE@XZ) referenced in function _main C:\[omitted]\Project2_2\Project2_2\program.obj  Project2_2

5 个答案:

答案 0 :(得分:14)

为什么不关注"Inclusion Model"?我建议你遵循那个模型。 编译器需要访问整个模板定义(而不仅仅是签名)才能为模板的每个实例化生成代码,因此您需要将函数的定义移动到标题中。

注意:通常,大多数C ++编译器不容易支持模板的单独编译模型。

此外,您需要阅读this.

答案 1 :(得分:4)

链接器错误是因为它看到了Queue.hpp的头文件,但没有看到函数的定义。这是因为它是一个模板类,对于C ++,模板的定义必须在头文件中(还有一些其他选项,但这是最简单的解决方案)。将函数的定义从Queue.cpp移到Queue.hpp,它应该编译。

答案 2 :(得分:4)

编译期间需要访问所有模板代码。将Queue.cpp实现详细信息移动到标头中,以便它们可用。

答案 3 :(得分:4)

如果你有:

template <typename T>
void foo();

你这样做:

foo<int>();

编译器需要生成(实例化)该函数。但除非函数定义在实例化时可见,否则它不能这样做。

这意味着模板定义需要以某种方式包含在标题中。 (您可以在标题的末尾添加.cpp,或者只提供内联定义。)

答案 4 :(得分:4)

解决错误lnk2019的一个例子:
它必须在.h文件末尾写#include“EXAMPLE.cpp”

//header file codes
#pragma once
#ifndef EXAMPLE_H
#define EXAMPLE_H

template <class T>
class EXAMPLE
{

//class members
void Fnuction1();

};


//write this
#include "EXAMPLE.cpp"


#endif
//----------------------------------------------

在.cpp文件中执行以下操作

//precompile header
#include "stdafx.h"
#pragma once
#ifndef _EXAMPLE_CPP_
#define _EXAMPLE_CPP_

template <class T> 
void EXAMPLE<T>::Fnuction1()
{
 //codes
}

#endif
//-----------------------------------------------