2009-05-17 30 views
44

Vì tôi đã tạo các tệp .cpp rồi chuyển chúng thành tệp .h, sự khác biệt duy nhất tôi có thể tìm thấy là bạn không thể #include .cpp tệp. Có bất kỳ sự khác biệt nào mà tôi đang thiếu không?Sự khác biệt giữa tệp .cpp và tệp .h là gì?

+7

thực sự, bạn có thể bao gồm tệp .cpp. Bạn có thể bao gồm bất cứ điều gì bạn muốn. –

+0

Để hiểu câu trả lời của mọi người bên dưới, bạn có thể cần phải đặt một câu hỏi khác: nghĩa là "Sự khác biệt giữa 'tuyên bố' và 'định nghĩa' trong C++ là gì?" – ChrisW

+1

Tôi biết sự khác biệt giữa tuyên bố và định nghĩa. –

Trả lời

42

Hệ thống xây dựng C++ (trình biên dịch) không biết sự khác biệt, vì vậy đó là tất cả các quy ước.

Quy ước là tệp .h là khai báo và tệp .cpp là định nghĩa.

Đó là lý do tại sao tệp .h đượC#bao gồm - chúng tôi bao gồm các khai báo.

+0

Hệ thống xây dựng C++ không phân biệt - hãy thử chạy g ++ trên tệp .h và tệp .cpp và xem điều gì xảy ra, ví dụ. –

+0

Tôi biết rằng các tệp .cpp được sử dụng (phần lớn thời gian) để xác định các hàm/lớp/v.v. đã được khai báo trong tệp .h, nhưng bạn cũng có thể xác định các biến trong tệp .h. –

+5

@Neil Butterworth: Có trình biên dịch G ++ hiểu quy ước, nhưng bạn có thể làm cho nó biên dịch bằng cách buộc ngôn ngữ. –

0

Theo quy ước, các tệp .h được bao gồm bởi các tệp khác và không bao giờ tự biên soạn trực tiếp. Các tệp .cpp - một lần nữa, theo quy ước - gốc rễ của quá trình biên dịch; chúng bao gồm các tệp .h trực tiếp hoặc gián tiếp, nhưng thường không phải tệp .cpp.

17

Tệp .cpp là đơn vị biên dịch: đó là tệp mã nguồn thực sẽ được biên dịch (bằng C++).

Tệp .h (tiêu đề) là các tệp sẽ được sao chép/dán trong tệp .cpp nơi lệnh #include precompiler xuất hiện. Khi mã tiêu đề được chèn vào trong mã .cpp, quá trình biên dịch của .cpp có thể bắt đầu.

+0

Tại sao bạn nói tệp .cpp chứ không phải tệp A.cpp? –

+9

@ Keand64: Bởi vì trình biên dịch chỉ xem * một tệp * .cpp tại một thời điểm khi biên dịch mọi thứ. Nó đọc một tệp .cpp, đọc tất cả các tệp #included .h, biên dịch toàn bộ nội dung, viết tệp .o (hoặc .obj) và sau đó tiến hành tệp .cpp tiếp theo. –

6

.h tệp hoặc tệp tiêu đề, được sử dụng để liệt kê các biến cá thể có thể truy cập công cộng và các phương thức trong khai báo lớp. Tệp .cpp hoặc tệp triển khai được sử dụng để thực sự triển khai các phương thức đó và sử dụng các biến mẫu đó.

Lý do chúng tách biệt là do tệp .h không được biên dịch thành mã nhị phân trong khi tệp .cpp là. Lấy một thư viện, ví dụ. Giả sử bạn là tác giả và bạn không muốn nó là nguồn mở. Vì vậy, bạn phân phối các thư viện nhị phân biên dịch và các tập tin tiêu đề cho khách hàng của bạn. Điều đó cho phép họ dễ dàng xem tất cả thông tin về các lớp thư viện của bạn mà họ có thể sử dụng mà không thể xem cách bạn triển khai các phương thức đó. Họ là nhiều hơn cho những người sử dụng mã của bạn chứ không phải là trình biên dịch. Như đã nói trước đây: đó là quy ước.

1

Những người khác đã đưa ra lời giải thích tốt, nhưng tôi nghĩ rằng tôi nên làm rõ sự khác nhau giữa các phần mở rộng khác nhau:

 
    Source Files for C: .c 
    Header Files for C: .h 

    Source Files for C++: .cpp 
    Header Files for C++: .hpp 

Tất nhiên, vì nó đã được chỉ ra, đây chỉ là ước. Trình biên dịch không thực sự chú ý đến chúng - nó hoàn toàn là vì lợi ích của bộ mã hóa.

+3

Hầu hết mọi người đều sử dụng .h cho C++. – Zifre

+0

@Zifre: Vâng, do đó tôi nói rằng đây là những * quy ước đặt tên được đề xuất *, mặc dù nhiều người có thể không tuân theo chúng. – Noldorin

1

Nguyên tắc chung là ".h tệp phải có khai báo [có khả năng] được nhiều tệp nguồn sử dụng, nhưng không có mã nào được chạy".

5

Tiêu đề (.h, .hpp, ...) Tập tin chứa

  • định nghĩa lớp (class X { ... };)
  • Inline định nghĩa hàm (inline int get_cpus() { ... })
  • tờ khai Function (void help();)
  • tờ khai Object (extern int debug_enabled;)

Một tập tin nguồn (.c , .cpp, .cxx) chứa

  • định nghĩa hàm (void help() { ... } hay void X::f() { ... })
  • định nghĩa Object (int debug_enabled = 1;)

Tuy nhiên, quy ước rằng tiêu đề được đặt tên với một .h hậu tố và nguồn tập tin được đặt tên với một hậu tố .cpp không phải là thực sự yêu cầu. Người ta luôn có thể nói cho một trình biên dịch tốt cách xử lý một số tệp, bất kể hậu tố tên tệp của nó (-x <file-type> cho gcc. Giống như -x c++).

Tệp nguồn sẽ chứa các định nghĩa chỉ được trình bày một lần trong toàn bộ chương trình. Vì vậy, nếu bạn bao gồm một tệp nguồn ở đâu đó và sau đó liên kết kết quả của việc biên dịch tệp đó và sau đó là tệp nguồn của chính nó, thì tất nhiên bạn sẽ gặp phải lỗi trình liên kết, vì bây giờ bạn có các định nghĩa đó xuất hiện hai lần: bao gồm tệp nguồn và sau đó trong tệp có chứa tệp đó. Đó là lý do tại sao bạn gặp sự cố với việc bao gồm tệp .cpp.

12

Tôi biết sự khác biệt giữa tuyên bố và định nghĩa.

Trong đó:

  • Một tập tin CPP bao gồm các định nghĩa từ bất kỳ tiêu đề mà nó bao gồm (vì CPP và phần đầu tập tin lại với nhau trở thành một 'đơn vị dịch thuật' duy nhất)
  • Một tập tin tiêu đề có thể được bao gồm bởi nhiều hơn một CPP nộp
  • Các mối liên kết thông thường sẽ không thích bất cứ điều gì được xác định trong tập tin nhiều hơn một CPP

Các refore bất kỳ định nghĩa nào trong tệp tiêu đề phải là nội dòng hoặc tĩnh. Các tệp tiêu đề cũng chứa các khai báo được sử dụng bởi nhiều tệp CPP.

Định nghĩa không phải là tĩnh và nội tuyến đều được đặt trong các tệp CPP. Ngoài ra, bất kỳ khai báo nào chỉ cần trong một tệp CPP thường được đặt trong chính tệp CPP đó, nstead của bất kỳ tệp tiêu đề (có thể chia sẻ) nào.

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