Tại sao việc triển khai và khai báo một lớp mẫu phải nằm trong cùng một tệp tiêu đề? Có thể nào bạn giải thích nó bằng ví dụ?Tại sao việc triển khai và khai báo một lớp mẫu phải nằm trong cùng một tệp tiêu đề?
Trả lời
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 phải di chuyển định nghĩa của hàm vào tiêu đề của mình.
Để biết thêm chi tiết, hãy đọc về The Inclusion Model.
Không, bạn không biết. nhưng tất nhiên quy tắc tiêu đề được thiết kế để giúp bạn tránh những điều vô nghĩa như vậy. :) –
@LightnessRacesinOrbit Tôi có thể hỏi TU là gì? – athos
@athos http://en.wikipedia.org/wiki/Translation_unit_%28programming%29 –
Định nghĩa của một mẫu lớp và việc thực hiện các chức năng thành viên của nó phải được hiển thị cho mọi nơi tạo ra nó với một kiểu riêng biệt. tức là để khởi tạo myTemplate<int>
, bạn cần xem định nghĩa đầy đủ và cách triển khai myTemplate
.
Cách dễ nhất để thực hiện việc này là đặt định nghĩa mẫu và chức năng thành viên của nó vào cùng một tiêu đề, nhưng có nhiều cách khác. Ví dụ: bạn có thể đặt các triển khai hàm thành viên trong một tệp riêng biệt được bao gồm riêng biệt. Sau đó, bạn có thể bao gồm nó từ tiêu đề đầu tiên hoặc chỉ bao gồm tệp triển khai nơi bạn cần.
Ví dụ: một thực hành là khởi tạo rõ ràng mẫu cho tập hợp tham số riêng biệt trong một tệp .cpp và khai báo những sự kiện đó extern
trong tiêu đề. Bằng cách này, các instantiations đó có thể được sử dụng trong các tệp nguồn khác mà không yêu cầu thực hiện các hàm thành viên mẫu để hiển thị. Tuy nhiên, trừ khi bạn bao gồm tệp triển khai, bạn sẽ không thể sử dụng các bộ tham số mẫu khác.
ví dụ: nếu bạn có myTemplate<int>
và myTemplate<std::string>
định nghĩa là extern
sau đó bạn có thể sử dụng chúng tốt, nhưng nếu myTemplate<double>
không được định nghĩa extern
thì bạn không thể sử dụng mà không thực hiện.
Trong trường hợp của một lớp bình thường, bản khai chỉ đủ để biên dịch và các định nghĩa tương ứng sẽ là được liên kết.
Trong trường hợp mẫu, trình biên dịch cũng cần định nghĩa để tạo mã.
Sự khác biệt được giải thích rõ hơn trong số C++ FAQ.
Họ không phải làm như vậy.
Điều cần thiết là định nghĩa mẫu hiển thị tại điểm diễn giải (nơi nó được sử dụng) để trình biên dịch có thể lấy được lớp/hàm từ mẫu tại thời điểm này.
Tuy nhiên nó là rất phổ biến để sử dụng hai tập tin tiêu đề cho mẫu lớp:
// foo_fwd.hpp
template <typename T, typename U> struct Foo;
// foo.hpp
#include "foo_fwd.hpp"
template <typename T, typename U> struct Foo { typedef std::pair<T,U> type; };
Điều này cho phép những người không cần mẫu định nghĩa đầy đủ bao gồm đầu trang có phần nhẹ hơn, ví dụ:
//is_foo.hpp
#include <boost/mpl/bool.hpp>
#include "foo_fwd.hpp"
template <typename Z>
struct is_foo: boost::mpl::false_ {};
template <typename T, typename U>
struct is_foo< Foo<T,U> >: boost::mpl::true_ {};
có thể tăng tốc độ biên dịch một chút.
- 1. Tại sao bao gồm tiêu đề và chuyển tiếp khai báo lớp chứa trong cùng một tệp cpp?
- 2. Tại sao Khai báo một loại trong cùng một tiêu đề tập tin như Tuyên bố Lớp
- 3. Khai báo đối tượng lớp trong tệp tiêu đề
- 4. Tại sao lớp java.util.Scanner được khai báo là 'cuối cùng'?
- 5. Lỗi định nghĩa ngoài dòng trên một lớp nhưng được khai báo trong tệp tiêu đề
- 6. Tại sao lớp của tôi không thể triển khai giao diện được khai báo bên trong?
- 7. Lý do cho '@ interface ViewController' trong cả tệp triển khai và tiêu đề cho một viewcontroller
- 8. Tại sao lớp composite-id phải triển khai Serializable?
- 9. Khai báo mảng C++ trong tiêu đề
- 10. Chuyên môn thành viên của lớp mẫu mà không cần khai báo trong tiêu đề
- 11. Khai báo một enum trong một lớp
- 12. Tại sao phương thức giao diện C# được triển khai trong một lớp là công khai?
- 13. Khai báo vectơ trong tệp tiêu đề C++
- 14. Nếu một lớp được khai báo là cuối cùng thì cần phải khai báo các phương thức như là số
- 15. Mục tiêu C: ARC với IV được khai báo trong tệp triển khai
- 16. Tại sao việc triển khai Externalizable lại cần một hàm tạo công khai mặc định?
- 17. Tôi có thể khai báo một chuỗi trong một tệp tiêu đề theo định nghĩa của một lớp không?
- 18. Tại sao lại khai báo một hàm trong chính?
- 19. Tại sao bạn lại muốn một tệp Java không có lớp công khai được khai báo trong đó?
- 20. Khai báo mẫu lớp kế thừa từ một mẫu lớp khác trong C++
- 21. Tại sao khai báo một đối số hàm để là kết quả cuối cùng?
- 22. Tại sao tôi nên khai báo một destructor ảo cho một lớp trừu tượng trong C++?
- 23. Cách trích xuất khai báo (tệp .hpp) từ việc triển khai (tệp .cpp)?
- 24. Các tệp triển khai khung UIKit nằm ở đâu?
- 25. Tại sao sử dụng macro trong khai báo lớp
- 26. Tại sao LESS không ghi đè thuộc tính được khai báo trong cùng một bộ chọn?
- 27. Tại sao một tệp Java có cùng tên với lớp công khai của nó?
- 28. Tại sao NULL không khai báo?
- 29. Tại sao tệp aspx code-behind được khai báo là các lớp một phần?
- 30. Java: mở rộng một lớp và triển khai một giao diện có cùng phương thức
chúng phải hiển thị trong cùng một đơn vị biên dịch.chúng có thể nằm trong các tệp khác nhau nếu cả hai được bao gồm – Anycorn
Thực tế không phải là không phổ biến để phân tách khai báo và triển khai trong hai tệp. Tiêu đề sẽ thường bao gồm tệp triển khai. – MSalters
@MSalters: Đó là vấn đề với các lớp mẫu, đó là những gì câu hỏi này là về. Tôi ước gì tôi có thể bình luận. –