# bao gồm .h hoặc .c / .cpp?


118

Khi viết mã bằng C hoặc C ++, tôi nên có #include's ở đâu?

callback.h:

#ifndef _CALLBACK_H_
#define _CALLBACK_H_

#include <sndfile.h>
#include "main.h"

void on_button_apply_clicked(GtkButton* button, struct user_data_s* data);
void on_button_cancel_clicked(GtkButton* button, struct user_data_s* data);

#endif

callback.c:

#include <stdlib.h>
#include <math.h>

#include "config.h"

#include "callback.h"
#include "play.h"

void on_button_apply_clicked(GtkButton* button, struct user_data_s* data) {
  gint page;
  page = gtk_notebook_get_current_page(GTK_NOTEBOOK(data->notebook));

  ...

Tất cả nên bao gồm ở dạng .h hoặc .c / .cpp, hoặc cả hai như tôi đã làm ở đây?


2
Hãy để tôi quay lại vấn đề này và hỏi: tiêu chí của bạn để quyết định đặt sndfile.h và main.h trong callback.h là gì?
Owen S.

Câu trả lời:


161

Đặt càng nhiều càng tốt vào .cvà ít nhất có thể vào .h. Các bao gồm trong .cchỉ được bao gồm khi một tệp đó được biên dịch, nhưng bao gồm .hphải được bao gồm bởi mọi tệp sử dụng nó.


6
Đúng, nhưng không phải #ifndef _CALLBACK_H_, trên hết, ngăn trình biên dịch xử lý nó nhiều lần?
hytromo

11
@ user9379 Điều đó sẽ ngăn nó được đưa vào nhiều hơn một lần cho mỗi tệp .c hoặc .cpp. Mặc dù vậy, mỗi tệp .c hoặc .cpp thường được tạo riêng lẻ, có nghĩa là .h sẽ được phân tích lại cho từng tệp .c hoặc .cpp mà bạn biên dịch.
Brendan Long

2
Tôi nghĩ rằng lý do chính để đặt càng ít càng tốt .hlà để tránh trong một số trường hợp xảy ra lỗi do một vòng lặp bao gồm. Ví dụ: hai lớp cần một lớp khác cho việc triển khai của chúng, nhưng không cần cho các khai báo của chúng. Đặt cả hai bao gồm trong .cpps sẽ tránh được lỗi.
Codoscope

1
@ Qu'est-cet'yont Đó là lý do tại sao bạn không thể đưa một số thứ nhất định vào tệp .h. Câu trả lời này là lý do tại sao bạn nên đặt thậm chí ít hơn thế.
Brendan Long

@BrendanLong Tôi hiểu rồi, mặc dù theo cảm nhận của tôi việc bao gồm nhiều lần một tiêu đề giống nhau không thành vấn đề nếu bạn đặt đúng macro bên trong để chỉ bao gồm nội dung một lần. Do đó, tôi nghĩ rằng đặt ít hơn nữa là để giảm khả năng xảy ra lỗi trong tương lai với các sửa đổi của mã.
Codoscope

55

Lần duy nhất bạn nên đưa tiêu đề vào trong một tệp .h khác là nếu bạn cần truy cập định nghĩa kiểu trong tiêu đề đó; ví dụ:

#ifndef MY_HEADER_H
#define MY_HEADER_H

#include <stdio.h>

void doStuffWith(FILE *f); // need the definition of FILE from stdio.h

#endif

Nếu tiêu đề A phụ thuộc vào tiêu đề B, chẳng hạn như ví dụ trên, thì tiêu đề A phải bao gồm trực tiếp tiêu đề B. Đừng KHÔNG cố gắng đặt hàng bao gồm của bạn trong file .c để đáp ứng phụ thuộc (có nghĩa là, trong đó có tiêu đề B trước khi tiêu đề A); đó là một đống lớn của chứng ợ nóng đang chờ đợi xảy ra. Ý tôi là nó. Tôi đã tham gia bộ phim đó vài lần, và nó luôn kết thúc với Tokyo trong biển lửa.

Có, điều này có thể dẫn đến việc các tệp được đưa vào nhiều lần, nhưng nếu chúng có các bộ bảo vệ bao gồm thích hợp được thiết lập để bảo vệ khỏi nhiều lỗi khai báo / định nghĩa, thì thời gian xây dựng thêm vài giây không đáng lo ngại. Cố gắng quản lý các phụ thuộc theo cách thủ công là một điều khó khăn.

Tất nhiên, bạn không nên bao gồm các tệp mà bạn không cần .


10

Đặt càng nhiều bao gồm trong cpp của bạn càng tốt và chỉ những cái cần thiết của tệp hpp trong hpp. Tôi tin rằng điều này sẽ giúp tăng tốc độ biên dịch, vì các tệp hpp sẽ ít được tham chiếu chéo hơn.

Ngoài ra, hãy xem xét sử dụng khai báo chuyển tiếp trong tệp hpp của bạn để giảm thêm chuỗi phụ thuộc bao gồm.


1
Ồ. Điều thú vị là khai báo phía trước.
Brendan Long

Parappa, khai báo chuyển tiếp rất hữu ích trong các kịch bản tham chiếu vòng tròn. Nhưng liệu chúng có phải là một thực hành tốt trong các tình huống khác? (Tôi mới trong C ++, vì vậy tôi thành thật xin)
Dzyann

5

Nếu tôi #include <callback.h>, tôi không muốn có #includenhiều tệp tiêu đề khác để có mã của tôi để biên dịch. Trong callback.hbạn nên bao gồm mọi thứ cần thiết để biên dịch chống lại nó. Nhưng không có gì hơn.

Cân nhắc xem việc sử dụng khai báo chuyển tiếp trong tệp tiêu đề của bạn (chẳng hạn như class GtkButton;) có đủ hay không, cho phép bạn giảm số lượng lệnh #includetrong tiêu đề (và đến lượt nó, thời gian biên dịch và độ phức tạp của tôi).


Tôi không đồng ý. Bao gồm cả thế giới trong tệp H làm tăng chuỗi phụ thuộc và do đó thời gian biên dịch.
John Dibling

Câu trả lời của tôi không khuyên bạn nên bao gồm toàn bộ thế giới trong tệp tiêu đề, tôi đề xuất bao gồm vừa đủ để người dùng API không phải mất thời gian tìm kiếm các phần phụ thuộc.
Johnsyweb
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.