2012-01-12 62 views
14

thể trùng lặp:
Why can templates only be implemented in the header file?Bao gồm tệp .cpp?

Tôi đã cố gắng xung quanh với C++ thời gian gần đây. Hiện tại tôi đang cố gắng lập trình một cái gì đó mà tôi chắc chắn đã từng thực hiện ít nhất một lần: Một lớp LinkedList đơn giản. Mã được thực hiện, nhưng tôi bằng cách nào đó không biên dịch được. Tôi đã googling và có vẻ như tôi đang liên kết các tập tin đối tượng sai. Đó là những gì mã của tôi về cơ bản trông giống như:

test.cpp

#include "linkedlist.h" 

int main() 
{ 
    LinkedList<int> list; 
    // do something 
} 

linkedlist.h

template <typename T> 
class LinkedList 
{ 
    // a lot of function and variable definitions 
} 

Sau đó có một file cpp gọi linkedlist.cpp chứa tất cả các mã thực tế của Lớp LinkerList. Khi cố gắng biên dịch test.cpp bằng cách sử dụng lệnh sau:

g++ ..\src\test.cpp 

Tôi được thông báo rằng có một tham chiếu không xác định đối với 'LinkedList :: LinkedList()'. Vì vậy, tôi đã nghĩ rằng nó được liên kết sai vì có nhiều hơn một tập tin .cpp, vì vậy tôi đã thử nó như thế này:

g++ -c -Wall -O2 ..\src\test.cpp 
g++ -c -Wall -O2 ..\src\linkedlist.cpp 
g++ -s test.o linkedlist.o 

Tuy nhiên, điều này không thay đổi bất cứ điều gì. Các thông báo lỗi vẫn giữ nguyên. Tôi đã cố gắng tìm một số thông tin trên internet, tuy nhiên, nó đã không thực sự làm việc ra ngoài.

+3

Thực hiện tốt để xây dựng điều này hoàn toàn và mạch lạc. :) Hiếm đối với người mới, ngày nay: ( –

+0

Vì 'LinkedList' là một lớp mẫu, người dùng của lớp đó cần định nghĩa đầy đủ của tất cả các phương thức. Một cách làm là có tất cả các phương thức nội tuyến trong lớp, trong khi một phương thức khác là Để đưa các phương thức vào một tập tin riêng biệt và đưa chúng vào trong tập tin tiêu đề –

+0

@Mike: Thật khó để gọi đó là một "trùng lặp" cho mỗi se.Đây là nơi mọi thứ trở nên mờ - câu hỏi hoàn toàn khác, mặc dù chúng ta không 't cần phải che phủ cùng một mặt đất một lần nữa. :) –

Trả lời

5

Bạn đang tạo mẫu lớp, có thông báo quan trọng là tất cả các định nghĩa biến phải được đặt trong tệp tiêu đề để chúng có thể truy cập được tới tất cả các đơn vị dịch trong quá trình biên dịch.

Lý do là cách các mẫu hoạt động. Trong quá trình biên dịch, trình biên dịch sẽ khởi tạo các lớp mẫu dựa trên định nghĩa mẫu lớp của bạn. Nó không đủ cho nó để có quyền truy cập vào chỉ các khai báo hoặc chữ ký: nó cần phải có toàn bộ định nghĩa có sẵn.

Di chuyển tất cả các định nghĩa phương thức của bạn ra khỏi tệp .cpp và vào tệp .h và mọi thứ sẽ ổn (giả sử bạn có, trên thực tế, đã cung cấp định nghĩa cho hàm tạo mặc định!). Ngoài ra, bạn có thể giải quyết vấn đề này bằng cách nói rõ trình biên dịch của bạn để khởi tạo lớp mẫu thích hợp bằng cách sử dụng một cái gì đó như template class LinkedList<int>, nhưng điều này thực sự không cần thiết trong một trường hợp đơn giản như vậy. Ưu điểm chính của việc này bao gồm tất cả các định nghĩa trong tệp tiêu đề là nó có khả năng làm giảm mã bloat và tăng tốc biên dịch. Nhưng nó có thể không cần thiết chút nào, vì các trình biên dịch đã trở nên thông minh hơn nhiều khi áp dụng các tối ưu thích hợp.

+2

Từ khóa 'export' không còn tồn tại nữa, và nó chỉ được hỗ trợ mơ hồ trước đây. –

2

Bạn đã chia lớp học của mình LinkedList và đặt tuyên bố vào tiêu đề và định nghĩa trong tệp nguồn. This does not work for a template. Cả hai phải nằm trong tiêu đề.

+0

Ông đã thực sự nói 'Sau đó, có một tập tin .cpp gọi là linkedlist.cpp trong đó có tất cả các mã thực tế của lớp LinkerList.' –

+0

Đó là những gì tôi nhận được chỉ là câu hỏi lướt - cố định nó. –

+0

Bạn được tha thứ cho những câu hỏi như thế này;) –

1

LinkedList là một lớp mẫu, the definitions of its member functions ought to go in a header.

(Họ không được, nói đúng, nhưng đây là cách dễ nhất để có được xung quanh sự phức tạp của mẫu instantiation mà không đi hoàn toàn off-piste với công ước inclusion).

Oh, và bạn vẫn cần phải tiếp cận giây thứ hai xây dựng; bạn nên liên kết với nhau tất cả các tệp .cpp hoặc sử dụng công tắc -c để biên dịch từng tệp một, sau đó liên kết kết quả với nhau sau này.

0

có một tài liệu tham khảo không xác định để 'LinkedList :: LinkedList()'

Bạn đã kiểm tra để xem nếu lớp LinkedList của bạn có một constructor?

1

Lớp mẫu giống như định nghĩa của quy tắc để xây dựng một lớp thực tế. Các lớp thực tế được tạo ra (instantiated) bởi trình biên dịch bất cứ nơi nào có instantiation của lớp mẫu. Vì lý do này, tất cả mã của lớp mẫu phải được hiển thị cho trình biên dịch tại điểm đó, và đó là lý do tại sao bạn phải viết tất cả các hàm và phương thức mẫu trong tệp tiêu đề - vì bạn chỉ bao gồm tiêu đề cho tệp cpp, chỉ hiển thị tiêu đề đến một trình biên dịch tại thời điểm đó. Bạn không bao gồm tệp cpp vào tệp cpp khác và bạn không bao giờ nên làm điều đó.

Khắc phục sự cố nếu hiểu biết của tôi sai.

P. S. C++ 11 có giải quyết vấn đề này không?

+1

P.S. Không, không. C++ 03 đã cố gắng và thất bại, vì vậy C++ 11 đã từ bỏ và thực sự loại bỏ các nỗ lực. –

Các vấn đề liên quan