2010-09-14 39 views
14

[[UPDATE]] -> Nếu tôi #include "Queue.cpp" trong program.cpp của tôi, nó hoạt động tốt. Điều này không cần thiết, phải không?C++ - LNK2019 lỗi không được giải quyết biểu tượng bên ngoài [constructor lớp mẫu và destructor] tham chiếu trong chức năng _main

Xin chào tất cả - Tôi đang sử dụng Visual Studio 2010 và gặp sự cố khi liên kết triển khai Hàng đợi nhanh chóng và bẩn. Tôi đã bắt đầu với trống Ứng dụng Bảng điều khiển Win32 và tất cả các tệp đều có trong dự án. Đối với verbosity, đây là mã hoàn chỉnh để nhân đôi lỗi của tôi. Tôi nhận ra một số mã có thể, trên thực tế, là sai. Tôi chưa có cơ hội để kiểm tra nó vì tôi chưa thể liên kết nó.

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

Và các lỗi ...

Error 1 error LNK2019: unresolved external symbol "public: __thiscall Queue<int>::~Queue<int>(void)" ([email protected]@@[email protected]) 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)" ([email protected]@@[email protected]) referenced in function _main C:\[omitted]\Project2_2\Project2_2\program.obj Project2_2 
+1

Cũng như ghi chú chung về mã; bạn không cần phải bao gồm bảo vệ cho mọi lớp trong một tiêu đề, và làm điều đó có nhiều khả năng xung đột hơn. Thay vào đó, đặt một bao gồm bảo vệ xung quanh toàn bộ tiêu đề, dựa trên tên tệp của tiêu đề đó. Đó là cả thực hành tiêu chuẩn và ít có khả năng chạy nhiều hơn vào các tên tệp khác. –

+0

Bản sao của [Lỗi liên kết LNK2019] (http://stackoverflow.com/questions/3680312/linker-error-lnk2019) (Câu hỏi này được hỏi khoảng năm lần mỗi tuần) –

Trả lời

13

Tại sao bạn không theo dõi "Inclusion Model"? Tôi khuyên bạn nên làm theo mô hình đó. Trình biên dịch cần phải có quyền truy cập vào toàn bộ định nghĩa mẫu (không chỉ chữ ký) để tạo mã cho mỗi phiên bản mẫu, vì vậy bạn cần di chuyển các định nghĩa của các hàm đến tiêu đề của bạn.

Lưu ý: Nói chung hầu hết các trình biên dịch C++ không dễ dàng hỗ trợ mô hình biên dịch riêng biệt cho các mẫu.

Bên cạnh đó bạn cần phải đọc this.

4

Lỗi trình liên kết là vì nó thấy các tệp tiêu đề cho Queue.hpp, nhưng không thấy định nghĩa của các hàm. Điều này là bởi vì nó là một lớp mẫu và đối với C++, các định nghĩa của các mẫu phải nằm trong tệp tiêu đề (có một vài tùy chọn khác, nhưng đó là giải pháp dễ nhất). Di chuyển các defintion của các hàm từ Queue.cpp sang Queue.hpp và nó sẽ biên dịch.

+0

Có, tất cả các tệp được bao gồm. Nếu tôi, ví dụ, bỏ qua một dấu chấm phẩy trong Queue.cpp, dự án không nhận được đến quá trình liên kết vì nó đột nhiên không biên dịch được. – Squirrelsama

+0

Tôi không nhận thấy đó là một mẫu trong lần vượt qua đầu tiên của tôi; giải thích lỗi. –

+0

Tại sao các mẫu gây ra lỗi này? Ngoài ra ... [[UPDATE]] -> Nếu tôi #include "Queue.cpp" trong program.cpp của tôi, nó hoạt động tốt. Điều này không cần thiết, phải không? – Squirrelsama

4

Tất cả mã mẫu cần phải có sẵn trong quá trình biên dịch. Di chuyển chi tiết triển khai Queue.cpp vào tiêu đề để chúng có sẵn.

4

Nếu bạn có:

template <typename T> 
void foo(); 

Và bạn làm:

foo<int>(); 

Trình biên dịch cần phải tạo ra (thuyết minh) chức năng đó. Nhưng nó không thể làm điều đó trừ khi định nghĩa chức năng có thể nhìn thấy tại thời điểm instantiation.

Điều này có nghĩa là các định nghĩa mẫu cần được bao gồm, theo một cách nào đó, trong tiêu đề. (Bạn có thể bao gồm các .cpp ở phần cuối của tiêu đề, hoặc chỉ cung cấp các định nghĩa inline.)

2

Một ví dụ để giải quyết lnk2019 lỗi:
Nó phải viết #include "EXAMPLE.cpp" ở phần cuối của .h tập tin

//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 
//---------------------------------------------- 

Trong tập tin cpp làm như sau

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

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

#endif 
//----------------------------------------------- 
Các vấn đề liên quan